在许多应用软件我们都可以看到 RememberMe 选项。如果我们勾选的话,下次访问就无须再登录。那么Spring Security是怎么实现 RememberMe 功能呢?我们基于数据库存储token的方式来实现 RememberMe。
RememberMe配置
这里配置是针对第4章改造的。这里主要替换 UserWebSecurityConfig 的 configure 方法
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/**").hasAnyRole("ADMIN")
.antMatchers("/hello2/").fullyAuthenticated()
.antMatchers("/rememberMe/").rememberMe()
.anyRequest().authenticated()
.and()
.formLogin()
.permitAll()
.and()
.rememberMe()
.tokenRepository(jdbcTokenRepository()).and()
.csrf().disable();
}
// 新增
@Autowired
private DataSource dataSource;
// 新增
public JdbcTokenRepositoryImpl jdbcTokenRepository() {
JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
jdbcTokenRepository.setDataSource(dataSource);
return jdbcTokenRepository;
}
数据库表
我们需要新增 persistent_logins 表。表的创建语句在 JdbcTokenRepositoryImpl 已经内置。
create table persistent_logins (
username varchar(64) not null,
series varchar(64) primary key,
token varchar(64) not null,
last_used timestamp not null
);
至此,RememberMe 功能就开发完成了。那么它是如何实现呢?
原理解析
涉及到的类
这里主要涉及到了 RememberMeAuthenticationFilter 过滤器 、 RememberMeServices 接口和他的实现类。

从登录地方开始
为什么我们勾选了就可以了,所以我们从登录地方开始追踪。我们可以发现 AbstractAuthenticationProcessingFilter 类完成登录时,我们会调用该类的 successfulAuthentication() 方法,然后这个方法又会调用 rememberMeServices#loginSuccess 方法进行处理。
rememberMeServices#loginSuccess 是实现 RememberMe 功能的入口。主要逻辑是,首先判断请求是否有 remember-me 参数并且该参数的值必须是 (true、on、yes、1)的其中一项。然后进入 AbstractRememberMeServices#onLoginSuccess 的方法,生成Token,存储Token到数据库,最后把Token写入 response.addCookie(cookie)。

RememberMeAuthenticationFilter 过滤器
上面登录成功后,就算我们重新打开浏览器,再次访问也无须进行登录。这是怎么做到呢?大致实现时序图如下所示。

备注
本系列都是学习《深入浅出Spring Security》的笔记
本文详细解读了如何在Spring Security中实现RememberMe功能,通过数据库存储token,配置过程和涉及的关键类,包括`JdbcTokenRepository`、`RememberMeAuthenticationFilter`和`RememberMeServices`。阅读者将了解登录流程和如何配置`HttpSecurity`以支持无痕登录。
3141

被折叠的 条评论
为什么被折叠?



