remember-me使得一次会话之后系统仍然记得会话的主体
- 通常是向浏览器发送cookie来实现的,之后的会话中可以检测到cookie并导致自动登录
- Spring Security为这些操作提供了必要的钩子,并有两个具体的记住我的实现。
- 一个使用散列法来保护基于cookie的令牌的安全性(不推荐),另一个使用数据库或其他持久性存储机制来存储生成的令牌
- remember-me功能依赖于UserDetailsService,如果使用的AuthenticationProvider没有使用UserDetailService,那么除非你的应用程序上下文中有UserDetailsService Bean,否则它不是不会工作的
Persistent Token Approach
数据库应该包含一个persistent_logins表,用以下SQL语句(或类似语句)创建。create table persistent_logins (username varchar(64) not null,
series varchar(64) primary key,
token varchar(64) not null,
last_used timestamp not null)
Remember-Me Interfaces and Implementations
Remember-me与UsernamePasswordAuthenticationFilter一起使用,并通过AbstractAuthenticationProcessingFilter超类中的钩子实现。它也被用于BasicAuthenticationFilter中。这些钩子将在适当的时候调用具体的RememberMeServices。该接口看起来像这样: ```java Authentication autoLogin(HttpServletRequest request, HttpServletResponse response);
void loginFail(HttpServletRequest request, HttpServletResponse response);
void loginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication);
不过在这个阶段要注意,AbstractAuthenticationProcessingFilter只调用loginFail()和loginSuccess()方法。每当SecurityContextHolder不包含一个Authentication时,RememberMeAuthenticationFilter就会调用autoLogin()方法。因此,这个接口为底层的remember-me实现提供了足够的认证相关事件的通知,并且每当候选网络请求可能包含cookie并希望被记住时,都会委托给该实现。这种设计允许任何数量的remember-me实现策略。我们在上面看到,Spring Security提供了两种实现方式。我们将依次看一下这些:
<a name="ugTHG"></a>
### PersistentTokenBasedRememberMeServices
这个类的使用方式与TokenBasedRememberMeServices相同,但它还需要配置一个PersistentTokenRepository来存储令牌。有两种标准的实现:
- InMemoryTokenRepositoryImpl,仅用于测试
- JdbcTokenRepositoryImpl,将令牌存储在数据库中
<a name="HDR0g"></a>
# conclusion
基于持久化token的remember-me实现方式
- 需要配置一个PersistentTokenRepository
- 使用该配置会在数据库中生成一个默认的表,如果不是第一次启动,应该注释掉这张表
- 需要在HTTPConfig中配置remember-me的具体项
- 开启该选项之后,登录成功后,会收到一个名为`JSSESIONID`的cookie,只要在提交请求的时候携带上改cookie,即可完成自动登录
```java
@Bean
public PersistentTokenRepository persistentTokenRepository() {
JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
jdbcTokenRepository.setDataSource(dataSource);
// 自动建表,第二次启动应该注释掉,默认创建的表名称为persistent_logins
// jdbcTokenRepository.setCreateTableOnStartup(true);
return jdbcTokenRepository;
}
// 应该在继承自WebSecurityConfigurerAdapter的类中配置
@Override
protected void configure(HttpSecurity http) throws Exception {
// remember-me配置
http.rememberMe()
.userDetailsService(userDetailsService)
.tokenValiditySeconds(14 * 24 * 3600)
.tokenRepository(persistentTokenRepository());
}