Spring Security框架下实现两周内自动登陆"记住我"功能

file

本文是Spring Security系列中的一篇。在上一篇文章中,咱们经过实现UserDetailsService和UserDetails接口,实现了动态的从数据库加载用户、角色、权限相关信息,从而实现了登陆及受权相关的功能。这一节就在此基础上新增,登陆过程当中常用的“记住我”功能,也就是咱们常常会在各类网站登录时见到的"两周内免登陆",“三天内免登陆”的功能。该功能的做用就是:当咱们登陆成功以后,必定的周期内当咱们再次访问该网站,不须要从新登陆。spring

1、最简实践

其实实现这个功能很是简单,只须要咱们在重写WebSecurityConfigurerAdapter 方法配置HttpSecurity 的时候增长rememberMe()方法。(下面代码中省略了大量的关于Spring Security登陆验证的配置,在本号此前的文章中已经讲过)数据库

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.rememberMe();   //实现记住我自动登陆配置,核心的代码只有这一行
    }
}

而后在登陆表单中加入一个checkbox勾选框,name属性的值目前必须是“remember-me”(个性化更改的方法后面会讲)。浏览器

<label><input type="checkbox" name="remember-me">自动登陆</label>

就是这么简单,咱们就实现了记住我功能,默认效果是:2周内免登陆。安全

2、实现原理

不少朋友可能看了上面的实现过程内心都犯懵,这样就实现了?下面和你们说明一下这过程当中间,都作了哪些事情。springboot

  • 当咱们登录的时候,除了用户名、密码,咱们还能够勾选remember-me。
  • 若是咱们勾选了remember-me,当咱们登陆成功以后服务端会生成一个Cookie返回给浏览器,这个Cookie的名字默认是remember-me;值是一个token令牌。
  • 当咱们在有效期内再次访问应用时,通过RememberMeAuthenticationFilter,读取Cookie中的token进行验证。验正经过不须要再次登陆就能够进行应用访问。

这个token令牌是一个 MD5 hash字符串:包含username、expirationTime和passwod和一个预约义的key,并将他们通过MD5加密。可能有的朋友会问:这样安全么?若是cookie被劫持,必定是不安全的,别人拿到了这个字符串在有效期内就能够访问你的应用。这就和你的钥匙token被盗了,你家确定不安全是一个道理。 可是不存在密码被破解为明文的可能性,MD5 hash是不可逆的。cookie

file

RememberMeAuthenticationFilter在Spring Security过滤器链中处于总体偏后的位置,因此只有当各类传统的登陆方式都没法完成验证的状况下,才走RememberMeAuthenticationFilter,这也是符合实际需求的。app

3、个性化配置

在实际的开发过程当中,咱们还能够根据需求作一些个性化的设置,以下:ide

.rememberMe()
    .rememberMeParameter("remember-me-new")
    .rememberMeCookieName("remember-me-cookie")
    .tokenValiditySeconds(2 * 24 * 60 * 60);
  • tokenValiditySeconds用于设置token的有效期,即多长时间内能够免除重复登陆,单位是秒。不修改配置状况下默认是2周。
  • 经过rememberMeParameter设置from表单“自动登陆”勾选框的参数名称。若是这里改了,from表单中checkbox的name属性要对应的更改。若是不设置默认是remember-me。
  • rememberMeCookieName设置了保存在浏览器端的cookie的名称,若是不设置默认也是remember-me。以下图中查看浏览器的cookie。

file

4、token数据库存储方式

上面咱们讲的方式,就是最简单的实现“记住我-自动登陆”功能的方式。这种方式的缺点在于:token与用户的对应关系是在内存中存储的,当咱们重启应用以后全部的token都将消失,即:全部的用户必须从新登录。为此,Spring Security还给咱们提供了一种将token存储到数据库中的方式,重启应用也不受影响。学习

> 有的文章说使用数据库存储方式是由于这种方式更安全,笔者不这么认为。虽然数据库存储的token的确再也不是用户名、密码MD5加密字符串了,而是一个随机序列号。可是一旦你的随机序列号cookie被劫持,效果是同样的。比如你家有把密码锁:你把钥匙丢了和你把密码丢了,危害性是同样的。网站

file

上图是token数据库存储方式的实现原理和验证过程,下面咱们就来实现一下。首先,咱们须要键一张数据库表persistent_logins:

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;

初始化一个PersistentTokenRepository类型的Spring bean,并将系统使用的DataSource注入到该bean中。(固然前提必定是你已经在Spring Boot的application.yml中配置好DataSource相关的链接属性,这里再也不赘述)

@Autowired
private DataSource dataSource;

 @Bean
 public PersistentTokenRepository persistentTokenRepository(){
     JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
     tokenRepository.setDataSource(dataSource);
     return tokenRepository;
 }

最后在Spring Security配置方法configure(HttpSecurity http)加上以下的个性化配置:

.rememberMe()
    .tokenRepository(persistentTokenRepository())

期待您的关注

相关文章
相关标签/搜索