基于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. ActiveMQ_Topic队列(三)

    一.本文章包含的内容 1.列举了ActiveMQ中通过Topic方式发送.消费队列的代码(监听者有两个,分别是topicMessageListener1.topicMessageListener2) ...

  2. s3c2440 移值u-boot-2016.03 第6篇 支持mtd yaffs 烧写

    1, 解决启动时的错误 Warning - bad CRC, using default environment 搜索发现 在 /tools/env/fw_env.c 中 /* 放在NAND FLAS ...

  3. CST和GMT时间的区别

    CST和GMT时间的区别 今天遇到一个奇怪的问题,在服务器端通过 c# 获取当前时间为 Fri Aug 28 09:37:46 CST 2009, 转化为 GMT时间为:28 Aug 2009 01: ...

  4. 把传统的基于sql的企业信息中心迁移到spark 架构应该考虑的几点思考...[修改中]

    把传统的基于sql的企业信息中心迁移到spark 架构应该考虑的几点 * 理由: 赶时髦,  这还不够大条么? > 数据都设计为NO-SQL模式, 只有需要search的才建立2级索引. 就可以 ...

  5. Bin &amp; Jing in wonderland(概率,组合数学)

    Problem 2103 Bin & Jing in wonderland Accept: 201    Submit: 1048 Time Limit: 1000 mSec    Memor ...

  6. perl 使用use utf8

    jrhapt12:/home/tomcat> cat a1.pl use Encode; $phone='18072722237'; open (LOG1 ,"<",' ...

  7. 计算机视觉与模式识别代码合集第二版three

    计算机视觉与模式识别代码合集第二版three     Topic Name Reference code Optical Flow Horn and Schunck's Optical Flow   ...

  8. org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: sys.entity.Role; nested exception is org.hibernate.PersistentObjectException: 的解决方案

    1.错误信息 org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist ...

  9. .Net 第三方工具包整理

    抓取数据 Jumony (http://www.jumony.net/)是一个基于 .NET 技术,用 C# 编写的一个 HTML 引擎,其可以用来分析解读 HTML 文档中的数据,也可以修改和绑定数 ...

  10. PAT 天梯赛 L2-007 家庭房产

    建图+DFS 题目链接:https://www.patest.cn/contests/gplt/L2-007 题解 在热身赛的时候没有做出来,用的并查集的思想,但是敲残了,最后也没整出来.赛后听到别人 ...