通过multipart / form-data POST请求实现文件上传。通常这是使用客户端AJAX完成的,但IE9不支持FileAPI(http://www.w3.org/TR/FileAPI/)。
IE9的解决方法是在隐藏的iframe中创建表单,然后提交表单。 CSRF令牌通过将其添加为表单输入而添加到请求正文中 - 原因是我无法操纵请求标头以在表单提交之前添加CSRF标头。
Spring Security的org.springframework.security.web.csrf.CsrfFilter首先尝试从头文件中获取CSRF令牌,如果没有找到,则尝试从参数中获取它(通过HttpServletRequest.getParameter())
这对于在正文中使用CSRF令牌的多部分请求不起作用 - getParameter()将始终返回null。
(顺便说一下,对getParameter()的调用也会将请求InputStream读取到最后,所以我们被迫在它到达CsrfFilter之前将请求换行,以便请求InputStream被'缓存' )
我想创建一个调用getPart()的CsrfFilter,但是在使用nice + clean的Spring Security XML命名空间元素时却不能这样做。
原因是在配置中没有地方包含自定义CSRF过滤器 - 并且CsrfConfigurer被硬编码为使用org.springframework.security.web.csrf.CsrfFilter,因此无法注入。
我可以将代码添加到我的请求包装器类的重写的getParameter()方法中,以尝试从多部分请求中解析参数 - 但实际上这是非常棘手的,并且宁愿避免这样的维护成本。
欢迎任何帮助 - 欢迎在客户端或服务器端修复建议!
TIA
答案 0 :(得分:5)
您应该阅读讨论CSRF and Multipart requests的参考资料中的部分。您有两种选择:
每个都有参考文献中描述的优点/缺点。
最终,如果你想提供一个自定义过滤器,你可以使用 XML element来实现,它只是引用一个实现过滤器的Spring Bean。例如:
<http ...>
...
<custom-filter ref="customCsrfFilter" position="CSRF_FILTER"/>
</http>
答案 1 :(得分:0)
我已经实施了一个似乎现在正在运行的解决方案,但有一些关于它我不喜欢......
<csrf>
我已在CSRF过滤器之前添加了自定义过滤器:
<security:custom-filter before="CSRF_FILTER" ref="csrfRequestWrapperFilter" />
HttpServletRequest
中的CsrfProtectedHttpServletRequest
,然后继续链(下一个是CsrfFilter)CsrfProtectedHttpServletRequest
扩展HttpServletRequestWrapper
,并覆盖getParameter(String name)方法。类似的东西:...将Request InputStream复制到成员OutputStream ...
if(this.getContentType() != null && requestBody != null) {
if(this.getContentType().contains(MediaType.APPLICATION_FORM_URLENCODED_VALUE) && requestBody.contains(parameterName+"="))
return getFormEncodedParameter(requestBody, parameterName);
else if(this.getContentType().contains(MediaType.MULTIPART_FORM_DATA_VALUE) && requestBody.contains("name="+"\""+ parameterName +"\"")) {
return getMultipartParameter(requestBody, parameterName);
}
}
}
这两种方法都做了一些字符串解析...那是我真正不喜欢的部分。它根本不与核心业务逻辑相关,而且我对实现并不是100%有信心,尽管它正在努力获得_csrf
&#34;参数&#34;超出多部分请求。