博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring Security笔记:解决CsrfFilter与Rest服务Post方式的矛盾
阅读量:4106 次
发布时间:2019-05-25

本文共 2761 字,大约阅读时间需要 9 分钟。

基于Spring Security+Spring MVC的web应用,为了防止跨站提交攻击,通常会配置csrf,即:

1     
2 ...3
4

如果应用中有Post方式访问的Rest服务(参考下面的代码),会很不幸的发现,所有POST方式请求的服务会调用失败。

1     @RequestMapping(value = "/user/create", method = RequestMethod.POST)2     @ResponseBody3     public UserInfo createUser(@RequestBody(required = true) UserInfo user,4             HttpServletRequest request, HttpServletResponse response)5             throws Exception {6         ...7     }

原因在于:启用csrf后,所有http请求都被会CsrfFilter拦截,而CsrfFilter中有一个私有类DefaultRequiresCsrfMatcher

1     private static final class DefaultRequiresCsrfMatcher implements RequestMatcher { 2         private Pattern allowedMethods = Pattern.compile("^(GET|HEAD|TRACE|OPTIONS)$"); 3  4         /* (non-Javadoc) 5          * @see org.springframework.security.web.util.matcher.RequestMatcher#matches(javax.servlet.http.HttpServletRequest) 6          */ 7         public boolean matches(HttpServletRequest request) { 8             return !allowedMethods.matcher(request.getMethod()).matches(); 9         }10     }

从这段源码可以发现,POST方法被排除在外了,也就是说只有GET|HEAD|TRACE|OPTIONS这4类方法会被放行,其它Method的http请求,都要验证_csrf的token是否正确,而通常post方式调用rest服务时,又没有_csrf的token,所以校验失败。

解决方法:自己弄一个Matcher

1 package com.cnblogs.yjmyzz.utils; 2  3 import java.util.List; 4 import java.util.regex.Pattern; 5  6 import javax.servlet.http.HttpServletRequest; 7  8 import org.springframework.security.web.util.matcher.RequestMatcher; 9 10 public class CsrfSecurityRequestMatcher implements RequestMatcher {11     private Pattern allowedMethods = Pattern12             .compile("^(GET|HEAD|TRACE|OPTIONS)$");13 14     public boolean matches(HttpServletRequest request) {15 16         if (execludeUrls != null && execludeUrls.size() > 0) {17             String servletPath = request.getServletPath();18             for (String url : execludeUrls) {19                 if (servletPath.contains(url)) {20                     return false;21                 }22             }23         }24         return !allowedMethods.matcher(request.getMethod()).matches();25     }26 27     /**28      * 需要排除的url列表29      */30     private List
execludeUrls;31 32 public List
getExecludeUrls() {33 return execludeUrls;34 }35 36 public void setExecludeUrls(List
execludeUrls) {37 this.execludeUrls = execludeUrls;38 }39 }

这里添加了一个属性execludeUrls,允许人为排除哪些url。

然后在配置文件里,这样修改:

1     
2 ... 3
4 ... 5
6
7 8
9
10
11
/rest/
12
13
14

这里约定所有/rest/开头的都是Rest服务地址,上面的配置就把/rest/排除在csrf验证的范围之外了.

转载地址:http://rynsi.baihongyu.com/

你可能感兴趣的文章
day_21_0817_Mysql
查看>>
day-22 mysql_SQL 结构化查询语言
查看>>
MySQL关键字的些许问题
查看>>
浅谈HTML
查看>>
css基础
查看>>
HTML&CSS进阶
查看>>
Servlet进阶和JSP基础
查看>>
servlet中的cookie和session
查看>>
过滤器及JSP九大隐式对象
查看>>
软件(项目)的分层
查看>>
菜单树
查看>>
MySQL-分布式架构-MyCAT
查看>>
设计模式六大原则(6):开闭原则
查看>>
阿里面试总结--JAVA
查看>>
Servlet的生命周期
查看>>
JAVA八大经典书籍,你看过几本?
查看>>
《读书笔记》—–书单推荐
查看>>
【设计模式】—-(2)工厂方法模式(创建型)
查看>>
有return的情况下try catch finally的执行顺序(最有说服力的总结)
查看>>
String s1 = new String("abc"); String s2 = ("abc");
查看>>