Spring Securityメモ:CsrfFilterとRestサービスPost方式の矛盾を解決します.
11416 ワード
Spring Security+Spring MVCによるwebアプリケーションは、クロスステーションからの攻撃を防ぐために、通常はcsrfが配置されます.
解決方法:自分でマッチを一つ作ります.
設定ファイルでこのように修正します.
1 <http ...>
2 ...
3 <csrf />
4 http>
Post方式でアクセスしたResetサービス(以下のコードを参照)が適用されている場合、すべてのPOST方式で要求されたサービスは起動に失敗します.1 @RequestMapping(value = "/user/create", method = RequestMethod.POST)
2 @ResponseBody
3 public UserInfo createUser(@RequestBody(required = true) UserInfo user,
4 HttpServletRequest request, HttpServletResponse response)
5 throws Exception {
6 ...
7 }
csrfを有効にすると、http要求は全部CsrfFilterによって阻止されます.Csrf Filterには私有類のDefaultRequires CsrfMatchがあります. 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_124; TRACE_OPTTIONSの4つの方法だけが実行されます.他のMethodのhttp要求は全部確認してください.csrfのtokenが正しいかどうかは、通常のpost方式でrestサービスを起動する時、またない.csrfのtokenは検証に失敗しました.解決方法:自分でマッチを一つ作ります.
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 = Pattern
12 .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 }
ここにはどんなurlを排除するために人為的に可能な属性execludeUrlsが追加されています.設定ファイルでこのように修正します.
1 <http entry-point-ref="loginEntryPoint" use-expressions="true">
2 ...
3 <intercept-url pattern="/rest/**" access="permitAll" />
4 ...
5 <csrf request-matcher-ref="csrfSecurityRequestMatcher"/>
6 http>
7
8 <beans:bean id="csrfSecurityRequestMatcher" class="com.cnblogs.yjmyzz.utils.CsrfSecurityRequestMatcher">
9 <beans:property name="execludeUrls">
10 <beans:list>
11 <beans:value>/rest/beans:value>
12 beans:list>
13 beans:property>
14 beans:bean>
ここですべての/rest/先頭を約束したのはすべてRestサービスアドレスで、上の構成はcsrf検証の範囲から除外されました.