Spring mvc 未找到预期的CSRF令牌。错误403
我有一个使用SpringSecurity3.2的SpringWeb应用程序。最初,我是根据内存中的凭据对用户进行身份验证。我的安全配置文件是:Spring mvc 未找到预期的CSRF令牌。错误403,spring-mvc,spring-security,csrf,Spring Mvc,Spring Security,Csrf,我有一个使用SpringSecurity3.2的SpringWeb应用程序。最初,我是根据内存中的凭据对用户进行身份验证。我的安全配置文件是: import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.config.annotation.web.builders.HttpSe
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.rememberme.InMemoryTokenRepositoryImpl;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.loginPage("/login")
.and()
.logout()
.logoutSuccessUrl("/")
.and()
.rememberMe()
.tokenRepository(new InMemoryTokenRepositoryImpl())
.tokenValiditySeconds(2419200)
.key("spittrKey")
.and()
.httpBasic()
.realmName("Spittr")
.and()
.authorizeRequests()
.antMatchers("/admin").authenticated()
.antMatchers("spitter/me").authenticated()
.antMatchers(HttpMethod.POST, "/spittles").authenticated()
.anyRequest().permitAll();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("admin").password("secman").roles("ADMIN").and()
.withUser("mike").password("secman").roles("USER");
}
}
我的应用程序的一部分有一个创建新帐户的页面:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<title>Spitter</title>
<link rel="stylesheet" type="text/css"
th:href="@{/resources/styles.css}"></link>
</head>
<body>
<div id="header" th:include="page :: header"></div>
<div id="content">
<h1>Register</h1>
<form method="POST" th:object="${spitter}">
<div class="errors" th:if="${#fields.hasErrors('*')}">
<h3 color="red">Please fix the following errors:</h3>
<ul class="errsul">
<li th:each="err : ${#fields.errors('*')}"
th:text="${err}">Input is incorrect</li>
</ul>
</div>
<label th:class="${#fields.hasErrors('firstName')}? 'error'">First Name</label>:
<input type="text" th:field="*{firstName}"
th:class="${#fields.hasErrors('firstName')}? 'error'" /><br/>
<label th:class="${#fields.hasErrors('lastName')}? 'error'">Last Name</label>:
<input type="text" th:field="*{lastName}"
th:class="${#fields.hasErrors('lastName')}? 'error'" /><br/>
<label th:class="${#fields.hasErrors('email')}? 'error'">Email</label>:
<input type="text" th:field="*{email}"
th:class="${#fields.hasErrors('email')}? 'error'" /><br/>
<label th:class="${#fields.hasErrors('username')}? 'error'">Username</label>:
<input type="text" th:field="*{username}"
th:class="${#fields.hasErrors('username')}? 'error'" /><br/>
<label th:class="${#fields.hasErrors('password')}? 'error'">Password</label>:
<input type="password" th:field="*{password}"
th:class="${#fields.hasErrors('password')}? 'error'" /><br/>
<label>Confirm Password</label>:
<input type="password" th:field="*{confirmPassword}" /><br/>
<input type="submit" value="Register" />
</form>
</div>
<div id="footer" th:include="page :: copy"></div>
</body>
</html>
当然,我还将数据源作为SecurityConfig.java中的私有属性进行自动连接。当我改为基于jdbc的身份验证时,在提交表单注册新帐户时,我突然开始出现CSRF null异常。根据关于这个问题的其他stackoverflow帖子,我必须在我的注册表中添加以下内容:
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>
这就解决了问题。我知道使用spring标记库会自动为您执行上述操作,使用
<form method="POST" th:action="@{/....}"/>
在你的表格上,但我都没有用。我的表单提交URL由GET请求中用于显示表单的URL暗示。所以我的问题是,我所做的唯一改变是从内存中的身份验证转向基于jdbc的身份验证。我所做的唯一更改是上面对SecurityConfig.java的更改。在这样做的过程中,CSRF滤波似乎从非活动变为活动。这听起来对吗?我在Spring安全文档页面上找不到任何提示。奇怪的是,从内存身份验证更改为jdbc身份验证将激活CSRF。那么您想禁用它吗?不,我不想禁用它,我知道怎么做。我只是想弄明白发生了什么。我认为在使用Java配置时,CSRF在Security2.3中默认处于活动状态。这似乎表明出于某种原因它不是活动的,至少在我转到jdbc身份验证之前是这样。我想不出我做的任何其他改变会影响CSRF。
<form method="POST" th:action="@{/....}"/>