禁用csrf后,我可以上传文件,但我需要启用它。问题仅发生在表单enctype是multipart/form-data时,即带有403的“无效CSRF令牌”。
通常,当我将enctype设置为多部分/表单数据时,即使对于没有文件上载的表单,也会出现相同的错误。
使用此依赖项:
<dependency>
<groupId>org.synchronoss.cloud</groupId>
<artifactId>nio-multipart-parser</artifactId>
<version>...</version>
</dependency>
尝试在表单中包含隐藏的csrf输入,并尝试将其附加到url,但出现相同错误
<form method="post" th:action="${'/add/' + id + '/documents?' + _csrf.headerName + '=' + _csrf.token}" enctype="multipart/form-data">
<input type="file" name="documents" multiple="multiple">
<input type="hidden"
th:name="${_csrf.headerName}"
th:value="${_csrf.token}" />
<input type="hidden" name="_csrf" th:value="${_csrf.token}">
<button class="btn btn-success btn-l">Upload</button>
</form>
对于csrf注入,有这样的控制器建议
@ControllerAdvice
public class SecurityAdvice {@ModelAttribute("_csrf")Mono<CsrfToken> csrfToken(final ServerWebExchange exchange) {
final Mono<CsrfToken> csrfToken = exchange.getAttributeOrDefault(org.springframework.security.web.server.csrf.CsrfToken.class.getName(), Mono.empty());
return csrfToken;
}
在安全方面,我有以下bean:
@Bean
public ServerCsrfTokenRepository csrfTokenRepository() {
WebSessionServerCsrfTokenRepository repository =
new WebSessionServerCsrfTokenRepository();
repository.setHeaderName("X-CSRF-TK");
return repository;
}
在我的SecurityWebFilterChain中这样使用它:
.and().csrf().csrfTokenRepository(csrfTokenRepository())
更新:
为几个URL禁用csrf也就足够了。找到了一些示例,但都是基于Servlet的版本。https://sdqali.in/blog/2016/07/20/csrf-protection-with-spring-security-and-angular-js/
您只需在过滤器链中启用它。
参考文件:
@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http
// ...
.csrf(csrf -> csrf.tokenFromMultipartDataEnabled(true))
return http.build();
}
看看Spring Security的官方建议:https://docs.spring.io/spring-security/site/docs/current/reference/html/csrf.html#csrf-多部分
基本上有两种方法:(1)将MultipartFilter放在Spring Security过滤器之前,以及(2)在表单操作中包含CSRF令牌,就像您正在做的那样。第一个选项是推荐的选项:
第一个选项是确保在Spring Security过滤器之前指定MultipartFilter。在Spring Security过滤器之前指定MultipartFilter意味着没有调用MultipartFilter的授权,这意味着任何人都可以在服务器上放置临时文件。但是,只有授权用户才能提交由您的应用程序处理的文件。通常,这是推荐的方法,因为临时文件上载对大多数服务器的影响应该可以忽略。
为确保MultipartFilter在带有java配置的Spring Security过滤器之前指定,用户可以在SpringSecurityFilterChain之前覆盖,如下所示:
public class SecurityApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
@Override
protected void beforeSpringSecurityFilterChain(ServletContext servletContext) {
insertFilters(servletContext, new MultipartFilter());
}
}
为了确保在使用XML配置的Spring Security过滤器之前指定MultipartFilter,用户可以确保将MultipartFilter的元素放置在web中springSecurityFilterChain之前。xml如下所示:
<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>
请注意,如果您仍然想使用表单操作,查询参数可能会泄露。尝试将您的“HeaderName”更改为“参数名称”:
<form action="./upload?${_csrf.parameterName}=${_csrf.token}" method="post" enctype="multipart/form-data">
编辑:如果您无法切换到基于servlet的容器(例如Jetty或Tomcat)并且表单操作建议不起作用,最近有一个Stack Overflow线程讨论了这个问题。
一位开发人员报告说,他使用AJAX解决了这个问题:
我通过以下方式解决了此问题:
var csrfToken=$(“meta[名称='\u csrf']”)。属性(“内容”);var csrfHeader=$(“meta[名称='\u csrf\u header']”)。属性(“内容”);XHR。setRequestHeader(csrfHeader、csrfToken);XHR。setRequestHeader('Content-Type','multipart/form data;boundary='boundary);XHR。发送(数据)
同一位开发人员向Spring报告了此问题,但尚未引起任何注意。
我想从angularJS客户端上传文件。我已经启用了CSRF保护,它可以正常工作,但当我尝试上载文件时,会出现错误: 在请求参数“_CSRF”或标头“X-XSRF-Token”上发现无效的CSRF令牌“null”。 但是令牌在请求头中,并且是正确的!当我禁用CSRF保护时,我可以毫无问题地上传文件。 除此之外,CSRF保护工作正常。 以下是我当前的配置: 安全Configuration.java
我正在尝试使用Spring MVC 4上载带有web应用程序的文件,但出现错误: 在请求参数“\u CSRF”或标头“X-CSRF-Token”上发现无效的CSRF令牌“null”。 Spring版本: Spring版本4.1.7。发布 Spring安全4.0.1。发布 代码: web.xml spring web servlet。xml Settings.jsp 提交名为test的文件后,发布请
此文件包含上载文件的表单 上传orm.jsp 我的控制器方法是 我上传时出现以下错误: HTTP状态403-在请求参数“\u CSRF”或标头“X-CSRF-Token”上发现无效的CSRF令牌“null” 我也用过Spring安全。但是我总是给出同样的错误。我尝试了很多,但无法解决它。你能帮忙解决这个问题吗?
我一直在使用Spring Security 3.2.0中的新csrf功能。并注意到它似乎不适用于enctype=“多部分/表单数据”表单。 我有一个简单的Spring形状: 隐藏的csrf输入按预期呈现: 但是请求没有通过csrf检查(如果我删除enctype="multipart/form-data",它会很好地工作)。我发现的唯一方法是附加“?_csrf=...”到我的操作url,这是丑陋的,
配置Spring Security 3.2后,csrf。令牌未绑定到请求或会话对象。 这是Spring Security配置: login.jsp文件 它呈现下一个html: 结果是403 HTTP状态: 在一些调试之后更新,请求对象以良好的形式发出DelegatingFilterProxy,但在CoyoteAdapter的469行中,它执行请求。回收();这会删除所有属性。。。 我使用JDK 1
问题内容: 我在网站上启用了CSRF保护,但是CSRF令牌唯一一次放置在隐藏字段中的时间是何时使用。我正在通过ajax发布数据,并且也需要发送CSRF以防止出现500个错误。 我以为有一种方法可以将CSRF令牌显式地嵌入到页面中,但是我似乎找不到它。 如果页面上没有表单,如何获得CSRF令牌? 问题答案: 您可以通过安全性类获取CSRF令牌名称和值: