02. Spring Security rememberMe
02. Spring Security rememberMe
参考:
https://blog.csdn.net/yuanlaijike/article/details/80249869
接着上一讲
修改login.html
使用简单的记住我, 但是不安全
#login.html
<div class="form">
<h3>账户登录</h3>
<input type="text" placeholder="用户名" name="username" required="required"/>
<input type="password" placeholder="密码" name="password" required="required"/>
<!-- 自动登入设置的name必须是remember-me-->
<label><input type="checkbox" name="remember-me"/>自动登录</label>
<button type="submit">登录</button>
</div>
添加rememberMe()
#配置类
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login").permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/").permitAll()
.and()
.logout()
.and()
.rememberMe();
}
默认cookie存储2周
Spring security 还提供了另一种相对更安全的实现机制:
在客户端的 Cookie 中,仅保存一个无意义的加密串(与用户名、密码等敏感数据无关),然后在数据库中保存该加密串-用户信息的对应关系,自动登录时,用 Cookie 中的加密串,到数据库中验证,如果通过,自动登录才算通过。
#基本原理
当浏览器发起表单登录请求时,当通过 UsernamePasswordAuthenticationFilter
认证成功后,会经过 RememberMeService
,在其中有个 TokenRepository
,它会生成一个 token
,首先将token 写入到浏览器的 Cookie 中,然后将 token、认证成功的用户名写入到数据库中。
当浏览器下次请求时,会经过 RememberMeAuthenticationFilter
,它会读取 Cookie 中的 token,交给 RememberMeService 从数据库中查询记录。如果存在记录,会读取用户名并去调用 UserDetailsService
,获取用户信息,并将用户信息放入Spring Security 中,实现自动登陆。
RememberMeAuthenticationFilter 在整个过滤器链中是比较靠后的位置,也就是说在传统登录方式都无法登录的情况下才会使用自动登陆。
#代码实现
首先需要创建一张表来存储 token 信息:
CREATE TABLE `persistent_logins` (
`username` varchar(64) NOT NULL,
`series` varchar(64) NOT NULL,
`token` varchar(64) NOT NULL,
`last_used` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`series`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
在 WebSecurityConfig 中注入 dataSource
,创建一个 PersistentTokenRepository
的Bean:
@Autowired
private DataSource dataSource;
@Bean
public PersistentTokenRepository persistentTokenRepository(){
JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
tokenRepository.setDataSource(dataSource);
// 如果token表不存在,使用下面语句可以初始化该表;若存在,请注释掉这条语句,否则会报错。
// tokenRepository.setCreateTableOnStartup(true);
return tokenRepository;
}
如果使用setCreateTableOnStartup(true)
则会再当前库中生成一个表名为persistent_logins
的表
修改配置中的登入设置
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login").permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/").permitAll()
.and()
.logout().permitAll()
.and()
//记住我默认2周
.rememberMe()
//设置token有效时间
.tokenValiditySeconds(60)
.tokenRepository(persistentTokenRepository());
.userDetailsService(userDetailsService);