基于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方式的矛盾的更多相关文章

  1. Spring Security笔记:HTTP Basic 认证

    在第一节 Spring Security笔记:Hello World 的基础上,只要把Spring-Security.xml里改一个位置 <http auto-config="true ...

  2. 【Spring学习笔记-MVC-4】SpringMVC返回Json数据-方式2

    <Spring学习笔记-MVC>系列文章,讲解返回json数据的文章共有3篇,分别为: [Spring学习笔记-MVC-3]SpringMVC返回Json数据-方式1:http://www ...

  3. 【Spring学习笔记-MVC-3】SpringMVC返回Json数据-方式1

    <Spring学习笔记-MVC>系列文章,讲解返回json数据的文章共有3篇,分别为: [Spring学习笔记-MVC-3]SpringMVC返回Json数据-方式1:http://www ...

  4. Spring Security笔记:自定义Login/Logout Filter、AuthenticationProvider、AuthenticationToken

    在前面的学习中,配置文件中的<http>...</http>都是采用的auto-config="true"这种自动配置模式,根据Spring Securit ...

  5. Spring Security笔记:Remember Me(下次自动登录)

    前一节学习了如何限制登录尝试次数,今天在这个基础上再增加一点新功能:Remember Me. 很多网站,比如博客园,在登录页面就有这个选项,勾选“下次自动登录”后,在一定时间段内,只要不清空浏览器Co ...

  6. Spring Security笔记:使用数据库进行用户认证(form login using database)

    在前一节,学习了如何自定义登录页,但是用户名.密码仍然是配置在xml中的,这样显然太非主流,本节将学习如何把用户名/密码/角色存储在db中,通过db来实现用户认证 一.项目结构 与前面的示例相比,因为 ...

  7. Spring Security笔记:Hello World

    本文演示了Spring Security的最最基本用法,二个页面(或理解成二个url),一个需要登录认证后才能访问(比如:../admin/),一个可匿名访问(比如:../welcome) 注:以下内 ...

  8. Spring Security笔记:登录尝试次数限制

    今天在前面一节的基础之上,再增加一点新内容,默认情况下Spring Security不会对登录错误的尝试次数做限制,也就是说允许暴力尝试,这显然不够安全,下面的内容将带着大家一起学习如何限制登录尝试次 ...

  9. Spring Security笔记:使用BCrypt算法加密存储登录密码

    在前一节使用数据库进行用户认证(form login using database)里,我们学习了如何把“登录帐号.密码”存储在db中,但是密码都是明文存储的,显然不太讲究.这一节将学习如何使用spr ...

随机推荐

  1. Struts2 Convention插件的使用(3)方法前的@Action注解

    package com.hyy.action; import org.apache.struts2.convention.annotation.Action; import com.opensymph ...

  2. Remote Desktop Organizer远程桌面管理软件的基本使用和介绍

    <Remote Desktop Organizer>是一款用于远程桌面管理的软件.软件支持windows平台运行. Remote Desktop Organizer 是一款 Windows ...

  3. iOS支付宝集成步骤;王刚韧的技术博客

  4. SQL 2008升级SQL 2008 R2完全教程或者10.00.4000升级10.50.1600

    今天将由于需要就将我的SQL 2008升级到SQL 2008 R2. 说到为什么要升级是因为,从另一台机器上备份了一个数据库,到我的机器上还原的时候提示“System.Data.SqlClient.S ...

  5. iOS中常见的锁

    多线程的安全隐患 一块资源可能会被多个线程共享,也就是说多个线程可能会访问同一块资源. 比如多个线程同时操作同一个对象,同一个变量. 当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题. 比 ...

  6. [HNOI2002]彩票

    题目描述 某地发行一套彩票.彩票上写有1到M这M个自然数.彩民可以在这M个数中任意选取N个不同的数打圈.每个彩民只能买一张彩票,不同的彩民的彩票上的选择不同. 每次抽奖将抽出两个自然数X和Y.如果某人 ...

  7. GitHub前50名的Objective-C动画相关库相关推荐,请自行研究

    GitHub的Objective-C的动画UI库其实是最多的一部分,GitHub有相当一部分的动画大牛,如Jonathan George,Nick Lockwood,Kevin,Roman Efimo ...

  8. Ubuntu如何启用root用户登录

    默认安装Ubuntu都是不允许以root用户进行登录的,想要以root用户进行登录需要进行一些操作,主要是以下几个步骤: 第一步 在终端输入命令:sudo passwd root 以普通用户登录系统, ...

  9. redis中的hash、列表、集合操作

    一.hash操作 数据结构:key:{k1:v1, k2:v2, k3:v3} 类似Python中的字典 如:info : {name: lina, age: 22, sex: F} hset key ...

  10. 认识:人工智能AI 机器学习 ML 深度学习DL

    人工智能 人工智能(Artificial Intelligence),英文缩写为AI.它是研究.开发用于模拟.延伸和扩展人的智能的理论.方法.技术及应用系统的一门新的技术科学. 人工智能是对人的意识. ...