spring security4.2 配置CSRF防御

时间:2022-11-04 18:28:06

spring security4.2 配置CSRF防御

注:源文请参考官方手册

最经项目用到csrf,看了官方文档后,结合实际开发过程,记录下所遇到的问题,其中第1、2、3点都没有什么问题。而是在使用文件上传时遇到问题,查了比较久的时间,从怀疑xhr对象,到跨域访问(用到的插件动态创建了一个iframe),最终发现是当form设置了enctype="multipart/form-data"之后,采用在form中插入标签的方法并不能通过验证,解决方法如4所述。其实这在官方文档,就在使用说明的下方就给出使用csrf的4个警告,当时没留意,想起这一点还是看到 multipart 后才觉得有点“眼熟”,然后再次看了之后,最终解决了上传文件失败的问题。记录下来,共勉之,同时有错的地方,还望浏览的“大虾们”不吝赐教啦

1.首先,确保在springSecurity.xml里没有把csrf关掉,即配置文件中不要出现以下代码:

<security:http>
<!--如果需要使用csrf,请注释下行配置-->
<security:csrf disabled="true"/>
</security:http>

尽量将涉及修改资源的请求改为POST

2.一般form表单 –参考这里

提交需要添加token,或者可以使用spring的标签<sec:csrfInput />,页面需要引入(有些ide可以实现自动引入如idea)

<%@ taglib prefix=”sec” uri=”http://www.springframework.org/security/tags” %>
如下所示:

<c:url var="logoutUrl" value="/logout"/>
<form action="${logoutUrl}"
method="post">

<input type="submit"
value="Log out" />

<input type="hidden"
name="${_csrf.parameterName}"
value="${_csrf.token}"/>

</form>

<!--或者使用标签-->
<form method="post" action="/do/something">
<sec:csrfInput />
Name:<br />
<input type="text" name="name" />
...
</form>

3.对于AjaxJSON请求–参考这里

需要在中如下设置,也有相应的spring的标签<sec:csrfMetaTags/>

<html>
<head>
<meta name="_csrf" content="${_csrf.token}"/>
<!-- default header name is X-CSRF-TOKEN -->
<meta name="_csrf_header" content="${_csrf.headerName}"/>
<!-- ... -->
</head>
<!-- ... -->

<!--或者使用标签-->
<!DOCTYPE html>
<html>
<head>
<title>CSRF Protected JavaScript Page</title>
<meta name="description" content="This is the description for this page" />

<sec:csrfMetaTags />

<script type="text/javascript" language="javascript">
<!--……-->
</head>
<!--……-->
</html

同时,需要在js中加入如下代码

$(function () {
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
$(document).ajaxSend(function(e, xhr, options) {
xhr.setRequestHeader(header, token);
});
});

4.上传文件,Multipart–参考这里

两个可选项来使用csrf:
- 将MultipartFilter放在Spring Security之前

<filter>
<filter-name>MultipartFilter</filter-name>
<filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
</filter>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>MultipartFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
  • 在action中添加CSRF token
<form action="./upload?${_csrf.parameterName}=${_csrf.token}" method="post" enctype="multipart/form-data">