Spring Security 4.0之后,引入了CSRF,默认是开启。不得不说,CSRF和RESTful技术有冲突。
CSRF默认支持的方法: GET|HEAD|TRACE|OPTIONS,不支持POST。
需要站点受到CSRF的保护,同时可以对外提供的REST服务,就需要开出一个隧道来。
这是网上的说法:
设置:
<beans:bean
>
<beans:property>
<beans:list>
<beans:value>/controller</beans:value>
</beans:list>
</beans:property>
</beans:bean>
代码:
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();
}
至少4.0.3版本时,发现隧道还是无法通过,主要是CSRF的下一个LogoutFilter居然调用了 DefaultRequiresCsrfMatcher ,而不是我们定义的 CsrfSecurityRequestMatcher,所以重写 CSFilter ,
设置:
<beans:bean
class="com.gdws.smw.util.CsrfFilter2">
<beans:constructor-arg>
<beans:bean
class="org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository" />
</beans:constructor-arg>
<beans:property>
<beans:list>
<beans:value>/controller</beans:value>
</beans:list>
</beans:property>
</beans:bean>
代码:
按照CsrfSecurityRequestMatcher重写DefaultRequiresCsrfMatcher。
这样,才是完全开启了这条隧道。