平时我们依赖于Session保存会话信息,一旦浏览器关闭再重新打开,会话信息会丢失,我们需要重新登录。我们可以使用RememberMe功能,及时关闭了浏览器再次打开,登录状态依然有效!

RememberMe的原理就是通过Cookie记录用户信息,用户登陆成功后会通过算法将用户信息,时间戳进行加密,存储在Cookie中,访问网站时会自动将Cookie中的信息发送给服务器,服务器进行校验,Cookie中保存的用户信息也是有时效性的,可以为三天,一周等

普通RememberMe

普通RememberMe 主要是调用了HttpSecurity中的rememberMe方法

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter{
@Override
protected void configure(HttpSecurity http) throws Exception{
 http.rememberMe()
      //设置一个key
     .key("javaboy");

}
}

同时在前端登录表格是传入一个叫remember-me的参数,使用该功能时值为on

需要注意的是普通的Remember安全隐患很大,一旦令牌泄露,恶意用户就可以使用这个令牌随意访问系统资源

持久化令牌

持久化令牌RememberMe就是在普通令牌的基础上新增了series和token两个字段,只有每次用户使用账号、密码登录时才会更新series字段,但是在每次产生新的会话时,token字段就会更新

一旦有用户盗用令牌进行访问成功后,token字段会发生改变,你就能发现令牌泄露并及时作出处理。

Spring Security对于持久化令牌提供了两种实现方式:JdbcTokenRepositoryImpl和 InMemoryTokenRepositoryImpl。前者是基于JdbcTemplate操纵数据库,后者是操作存储在内存中的数据。

InMemoryTokenRepositoryImpl的使用场景很少,我们一般使用JdbcTokenRepositoryImpl

(1)首先我们需要一张表 记录令牌信息 脚本在JdbcTokenRepositoryImpl类中的CREATE_TABLE_SQL变量中

CREATE TABLE persistent_logins (
  username varchar(64) not null,
  series varchar(64) not null,
  token varchar(64) not null,
  last_used timestamp not null,
  PRIMARY KEY (series)
);

(2)在application.properties中配置数据库连接信息

spring.datasource.url=
spring.datasource.username=
spring.datasource.password=

(3)修改配置类

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter{

@Autowired
DataSource dataSource;



//生成JdbcTokenRepositoryImpl实例,并注入数据源
@Bean
JdbcTokenRepositoryImpl jdbcTokenRepositoryImpl(){
JdbcTokenRepositoryImpl jdbcTokenRepositoryImpl=new JdbcTokenRepositoryImpl();
jdbcTokenRepositoryImpl.setDataSource(dataSource);
return jdbcTokenRepositoryImpl;
}


@Override
protected void configure(HttpSecurity http) throws Exception{
  http.authorizeRequests()
      .anyRequest().authenticated()
      .and()
     .formLogin()
      .and()
      .rememberMe()
       //设置tokenRepository
      .tokenRepository(jdbcTokenRepositoryImpl())
      .and()
       .csrf().disable();

}
}

二次校验

二次校验是指即使用户使用了RememberMe功能 在访问某些接口时,仍需要登录

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter{

@Autowired
DataSource dataSource;



//生成JdbcTokenRepositoryImpl实例,并注入数据源
@Bean
JdbcTokenRepositoryImpl jdbcTokenRepositoryImpl(){
JdbcTokenRepositoryImpl jdbcTokenRepositoryImpl=new JdbcTokenRepositoryImpl();
jdbcTokenRepositoryImpl.setDataSource(dataSource);
return jdbcTokenRepositoryImpl;
}


@Override
protected void configure(HttpSecurity http) throws Exception{
  http.authorizeRequests()
      .antMatchers("/admin").fullyAuthenticated()
      .antMatchers("/rememberme").rememberMe()
      .anyRequest().authenticated()
      .and()
     .formLogin()
      .and()
      .rememberMe()
       //设置tokenRepository
      .tokenRepository(jdbcTokenRepositoryImpl())
      .and()
       .csrf().disable();

}
}

配置完成后 我们发现在登录完成后,使用RememberMe功能,可以访问/rememberme,但是访问/admin仍然需要再次登录。