我有一个使用Spring Security 3.2的Spring Web应用程序。最初我是针对内存凭据对用户进行身份验证。我的安全配置文件是:
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>
以角色身份登录USER或ADMIN工作正常,就像创建新帐户一样。我没有显示控制器,因为我认为它们与我的问题无关。我更改了安全配置,以便我现在对MySQL数据库中的帐户表进行身份验证。对SecutrityConfig.java的更改在configure方法中:
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery("select username, password, enabled"
+" from account where username = ?")
.authoritiesByUsernameQuery("select a.username, r.name from account a,"
+" role r, account_role ar where ar.account_id = a.id"
+" and ar.role_id = r.id and a.username = ?");
}
当然,我还将我的dataSource自动装入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 Security文档页面上找不到任何内容来表明这一点。