在Spring Security4中引入的CSRF是不错的安全机制. 但在常用的上传文件中(form提交, post, 使用commons-fileupload)会导致CSRF失效,
这问题的根源在于CSRF无法获取表单中的_csrf 的值引起的(可在CsrfFilter打断点查看).
之前我也被这问题困惑了一天, 不知如何是好.
解决之道如下:
1.升级项目中使用的Servlet API版本至3.0及以上.
2.不要使用commons-fileupload组件,即
CommonsMultipartResolver
StandardServletMultipartResolver其在Spring MVC中的配置如下:
<bean id="multipartResolver" class="org.springframework.web.multipart.support.StandardServletMultipartResolver"> </bean>
<multipart-config> <!--location>/tmp</location--> <max-file-size>1000000</max-file-size> </multipart-config>
<servlet> <servlet-name>mvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>2</load-on-startup> <multipart-config> <!--location>/tmp</location--> <max-file-size>1000000</max-file-size> </multipart-config> </servlet> <servlet-mapping> <servlet-name>mvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
注意在升级Servlet API后需要将web.xml的状况声明也更新为3.0的,如下:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
分析大概的原因是commons-fileupload组件对request进行封装时对CSRF的支持有问题. 没将_csrf值传递.
参考文章: http://stackoverflow.com/questions/25185578/spring-security-3-2-csrf-and-multipart-requests