Spring Security笔记:解决CsrfFilter与Rest服务Post方式的矛盾
基于Spring Security+Spring MVC的web应用,为了防止跨站提交攻击,通常会配置csrf,即:
<http ...>
...
<csrf />
</http>
如果应用中有Post方式访问的Rest服务(参考下面的代码),会很不幸的发现,所有POST方式请求的服务会调用失败。
@RequestMapping(value = "/user/create", method = RequestMethod.POST)
@ResponseBody
public UserInfo createUser(@RequestBody(required = true) UserInfo user,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
...
}
原因在于:启用csrf后,所有http请求都被会CsrfFilter拦截,而CsrfFilter中有一个私有类DefaultRequiresCsrfMatcher
private static final class DefaultRequiresCsrfMatcher implements RequestMatcher {
private Pattern allowedMethods = Pattern.compile("^(GET|HEAD|TRACE|OPTIONS)$");
/* (non-Javadoc)
* @see org.springframework.security.web.util.matcher.RequestMatcher#matches(javax.servlet.http.HttpServletRequest)
*/
public boolean matches(HttpServletRequest request) {
return !allowedMethods.matcher(request.getMethod()).matches();
}
}
从这段源码可以发现,POST方法被排除在外了,也就是说只有GET|HEAD|TRACE|OPTIONS这4类方法会被放行,其它Method的http请求,都要验证_csrf的token是否正确,而通常post方式调用rest服务时,又没有_csrf的token,所以校验失败。
解决方法:自己弄一个Matcher
package com.cnblogs.yjmyzz.utils; import java.util.List;
import java.util.regex.Pattern; import javax.servlet.http.HttpServletRequest; import org.springframework.security.web.util.matcher.RequestMatcher; public class CsrfSecurityRequestMatcher implements RequestMatcher {
private Pattern allowedMethods = Pattern
.compile("^(GET|HEAD|TRACE|OPTIONS)$"); public boolean matches(HttpServletRequest request) { if (execludeUrls != null && execludeUrls.size() > 0) {
String servletPath = request.getServletPath();
for (String url : execludeUrls) {
if (servletPath.contains(url)) {
return false;
}
}
}
return !allowedMethods.matcher(request.getMethod()).matches();
} /**
* 需要排除的url列表
*/
private List<String> execludeUrls; public List<String> getExecludeUrls() {
return execludeUrls;
} public void setExecludeUrls(List<String> execludeUrls) {
this.execludeUrls = execludeUrls;
}
}
这里添加了一个属性execludeUrls,允许人为排除哪些url。
然后在配置文件里,这样修改:
<http entry-point-ref="loginEntryPoint" use-expressions="true">
...
<intercept-url pattern="/rest/**" access="permitAll" />
...
<csrf request-matcher-ref="csrfSecurityRequestMatcher"/>
</http> <beans:bean id="csrfSecurityRequestMatcher" class="com.cnblogs.yjmyzz.utils.CsrfSecurityRequestMatcher">
<beans:property name="execludeUrls">
<beans:list>
<beans:value>/rest/</beans:value>
</beans:list>
</beans:property>
</beans:bean>
这里约定所有/rest/开头的都是Rest服务地址,上面的配置就把/rest/排除在csrf验证的范围之外了.
Spring Security笔记:解决CsrfFilter与Rest服务Post方式的矛盾的更多相关文章
- Spring Security笔记:HTTP Basic 认证
在第一节 Spring Security笔记:Hello World 的基础上,只要把Spring-Security.xml里改一个位置 <http auto-config="true ...
- 【Spring学习笔记-MVC-4】SpringMVC返回Json数据-方式2
<Spring学习笔记-MVC>系列文章,讲解返回json数据的文章共有3篇,分别为: [Spring学习笔记-MVC-3]SpringMVC返回Json数据-方式1:http://www ...
- 【Spring学习笔记-MVC-3】SpringMVC返回Json数据-方式1
<Spring学习笔记-MVC>系列文章,讲解返回json数据的文章共有3篇,分别为: [Spring学习笔记-MVC-3]SpringMVC返回Json数据-方式1:http://www ...
- Spring Security笔记:自定义Login/Logout Filter、AuthenticationProvider、AuthenticationToken
在前面的学习中,配置文件中的<http>...</http>都是采用的auto-config="true"这种自动配置模式,根据Spring Securit ...
- Spring Security笔记:Remember Me(下次自动登录)
前一节学习了如何限制登录尝试次数,今天在这个基础上再增加一点新功能:Remember Me. 很多网站,比如博客园,在登录页面就有这个选项,勾选“下次自动登录”后,在一定时间段内,只要不清空浏览器Co ...
- Spring Security笔记:使用数据库进行用户认证(form login using database)
在前一节,学习了如何自定义登录页,但是用户名.密码仍然是配置在xml中的,这样显然太非主流,本节将学习如何把用户名/密码/角色存储在db中,通过db来实现用户认证 一.项目结构 与前面的示例相比,因为 ...
- Spring Security笔记:Hello World
本文演示了Spring Security的最最基本用法,二个页面(或理解成二个url),一个需要登录认证后才能访问(比如:../admin/),一个可匿名访问(比如:../welcome) 注:以下内 ...
- Spring Security笔记:登录尝试次数限制
今天在前面一节的基础之上,再增加一点新内容,默认情况下Spring Security不会对登录错误的尝试次数做限制,也就是说允许暴力尝试,这显然不够安全,下面的内容将带着大家一起学习如何限制登录尝试次 ...
- Spring Security笔记:使用BCrypt算法加密存储登录密码
在前一节使用数据库进行用户认证(form login using database)里,我们学习了如何把“登录帐号.密码”存储在db中,但是密码都是明文存储的,显然不太讲究.这一节将学习如何使用spr ...
随机推荐
- Mac OS 文件、文件夹重命名的方法
在Mac OS中,文件和文件名重命名的方法非常简单 选中你想要命名的文件或者文件夹,按回车,可以直接重命名,输入你要修改的内容,确认后,再按回车就OK啦--- 希望能对你有所帮助^_^
- Servlet简介与Servlet和HttpServlet运行的流程
1.Servlet [1] Servlet简介 > Server + let > 意为:运行在服务器端的小程序. > Ser ...
- informatica powercenter学习笔记(LookUp 使用)
LOOKUP TRANSFORMATION的使用点评: LOOKUP基本用法不熟的话请参考下附属信息. 用法感受: 1 LOOKUP的作用跟我们以前在EXCEL的函数功能类似,就是隔表取值.优点就是用 ...
- Javascript之旅——第八站:说说instanceof踩了一个坑
前些天写js遇到了一个instanceof的坑,我们的页面中有一个iframe,我在index页面中计算得到了一个array,然后需要传递到Flight页面 这个嵌套的iframe中的一个函数(Sea ...
- Tomcat源码分析之—容器整体结构
Tomcat有多个容器组成,而Container也就是容器与Connecter连接器是Tomcat最核心的两个模块,Connecter连接器接收客户端的请求,并根据客户端的请求传递给Container ...
- ixgbe rx_missed_errors
https://communities.intel.com/thread/54600?start=0&tstart=0 I am acquiring 800Mb/sec+ multicast ...
- Javascript进度条
一个简单的进度条演示. <!doctype html> <html> <head> <meta charset="utf8"> &l ...
- 利用网络流传的WebShell默认密码库寻找WebShell
声明:本文提到的技术,仅可用作网络安全加固等合法正当目的.本文作者无法鉴别判断读者阅读本文的真实目的,敬请读者在本国法律所允许范围内阅读本文,读者一旦因非法使用本文提到技术而违反国家相关的法律法规,所 ...
- Linux内核源码树建立加载hello模块
在加载模块之前,书中说要先建立内核源码树,那么,如何建立内核源码树呢? 首先,要先知道你的OS的内核版本,用uname -r可以查得到 在/url/src/目录下可以看到对应的版本目录 如果没有可以用 ...
- MySQL Database on Azure 的用户名
MySQL Database on Azure是中国版Windows Azure上的一个PaaS服务,类似于AWS上的RDS.MySQL Database on Azure的用户名与on-premis ...