配置Spring Security 3.2后,_csrf.token不会绑定请求或会话对象.
这是spring security配置:
<http pattern="/login.jsp" security="none"/>
<http>
<intercept-url pattern="/**" access="ROLE_USER"/>
<form-login login-page="/login.jsp"
authentication-failure-url="/login.jsp?error=1"
default-target-url="/index.jsp"/>
<logout/>
<csrf />
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="test" password="test" authorities="ROLE_USER/>
</user-service>
</authentication-provider>
</authentication-manager>
Run Code Online (Sandbox Code Playgroud)
login.jsp文件
<form name="f" action="${contextPath}/j_spring_security_check" method="post" >
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
<button id="ingresarButton"
name="submit"
type="submit"
class="right"
style="margin-right: 10px;">Ingresar</button>
<span>
<label for="usuario">Usuario :</label>
<input type="text" name="j_username" id="u" class="" value=''/>
</span>
<span>
<label for="clave">Contraseña :</label>
<input type="password"
name="j_password"
id="p"
class=""
onfocus="vc_psfocus = 1;"
value="">
</span>
</form>
Run Code Online (Sandbox Code Playgroud)
它呈现下一个HTML:
<input type="hidden" name="" …Run Code Online (Sandbox Code Playgroud) 我们已经将Spring Security与我们的应用程序一起使用了几年.上周我们将Spring Security从3.1.4升级到3.2.0.升级很顺利,我们在升级后没有发现任何错误.
在查看Spring Security 3.2.0文档时,我们遇到了围绕CSRF保护和安全头的新增功能.我们按照Spring Security 3.2.0文档中的说明为受保护资源启用CSRF保护.它适用于常规表单,但不适用于我们的应用程序中的多部分表单.在表单提交时,CsrfFilter引发拒绝访问错误,引用请求中缺少CSRF令牌(通过DEBUG日志确定).我们尝试使用Spring Security文档中建议的第一个选项来使CSRF保护与多部分表单一起工作.我们不想使用第二个建议的选项,因为它通过URL泄漏CSRF令牌并带来安全风险.
基于文档的配置的相关部分在Github上作为Gist提供.我们使用的是Spring 4.0.0版.
请注意,我们已尝试以下变体但未成功:
MultipartFilter进入web.xml.MultipartFilterin 设置解析器bean名称web.xml.filterMultipartResolver在webContext.xml.更新:我已经确认即使使用单页示例应用程序,记录的行为也不起作用.任何人都可以确认记录的行为按预期工作吗?是否有可以使用的示例工作应用程序?
我用,
其中,我使用内置安全令牌来防范CSRF攻击.
<s:form namespace="/admin_side"
action="Category"
enctype="multipart/form-data"
method="POST"
validate="true"
id="dataForm"
name="dataForm">
<s:hidden name="%{#attr._csrf.parameterName}"
value="%{#attr._csrf.token}"/>
</s:form>
Run Code Online (Sandbox Code Playgroud)
它是其中CSRF令牌是不可用的,除非春季安全多部分请求MultipartFilter连同MultipartResolver被适当地配置成使得所述多请求由弹簧处理.
MultipartFilterin web.xml配置如下.
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
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">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext.xml
/WEB-INF/spring-security.xml
</param-value>
</context-param>
<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>
<filter>
<filter-name>AdminLoginNocacheFilter</filter-name>
<filter-class>filter.AdminLoginNocacheFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AdminLoginNocacheFilter</filter-name>
<url-pattern>/admin_login/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>NoCacheFilter</filter-name>
<filter-class>filter.NoCacheFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>NoCacheFilter</filter-name>
<url-pattern>/admin_side/*</url-pattern> …Run Code Online (Sandbox Code Playgroud) 我想从我的angularJS客户端上传文件.我启用了CSRF保护,它工作正常,除非我尝试上传文件,我得到一个403错误:
在请求参数'_csrf'或标题'X-XSRF-TOKEN'上找到无效的CSRF令牌'null'.
但令牌位于请求标头中并且是正确的!当我禁用CSRF保护时,我可以毫无问题地上传文件.
除此之外,CSRF保护工作正常.
这是我目前的配置:
SecurityConfiguration.java
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private SecurityUserDetailsService securityUserDetailsService;
@Autowired
private AuthFailureHandler authFailureHandler;
@Autowired
private AjaxAuthSuccessHandler ajaxAuthSuccessHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.exceptionHandling()
.authenticationEntryPoint(authFailureHandler)
.and()
.authorizeRequests()
.antMatchers(
"/",
"/index.html",
"/styles/**",
"/bower_components/**",
"/scripts/**"
).permitAll().anyRequest()
.authenticated()
.and().formLogin().loginPage("/login").permitAll()
.and().logout().logoutUrl("/logout").logoutSuccessHandler(ajaxAuthSuccessHandler).permitAll()
.and().httpBasic()
.and().addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class)
.csrf().csrfTokenRepository(csrfTokenRepository());
}
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName("X-XSRF-TOKEN");
return repository;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(securityUserDetailsService)
.passwordEncoder(new …Run Code Online (Sandbox Code Playgroud) 禁用 csrf 后,我可以上传文件,但需要启用它。该问题仅在表单 enctype 为 multipart/form-data 时出现,即 403 的“无效 CSRF 令牌”。
通常,即使对于没有文件上传的表单,当我将 enctype 设置为 multipart/form-data 时,也会出现相同的错误。
使用此依赖项:
<dependency>
<groupId>org.synchronoss.cloud</groupId>
<artifactId>nio-multipart-parser</artifactId>
<version>...</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)
尝试在表单中包含隐藏的 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>
Run Code Online (Sandbox Code Playgroud)
有这样的控制器建议用于 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;
} …Run Code Online (Sandbox Code Playgroud) spring multipartform-data spring-security spring-boot spring-webflux
我一直在使用Spring Security 3.2.0.RC1中的新csrf功能,并注意到它似乎不适用于enctype ="multipart/form-data"表单.
我有一个简单的Spring表单:
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
...
<form:form action="${pageContext.request.contextPath}/model/create" modelAttribute="myForm" enctype="multipart/form-data">
Run Code Online (Sandbox Code Playgroud)
隐藏的csrf输入正在按预期呈现:
<input type="hidden" value="..." name="_csrf">
Run Code Online (Sandbox Code Playgroud)
但请求未通过csrf检查(如果我删除enctype ="multipart/form-data",它可以正常工作).我找到的唯一方法是将"?_csrf = ..."附加到我的动作网址,这很难看,因为令牌会出现在重定向的地址栏中.有没有人经历过相同/找到一个很好的解决方案?
通过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