原创

Spring Security(3)——实现基于数据库的Remember Me功能(附完整项目代码)

1. 基于内存实现Remember Me功能的问题

在上篇文章Spring Security(1)——基于内存认证信息(附完整项目代码)已经完成了RememberMe基于内存的demo,测试可以看到token数据是保存在内存的,但是这种情况会有两个弊端:

一 : 如果服务重启了或者宕机了,那么登入的token数据就会丢失,那么用户就需要重新登入。

二 : 集群模式下的服务,用户登入的token保存在某个服务器上,是不共享的,那么这个时候如果用户请求分发到另外一个服务器,用户还需要重新登入。

2. 基于数据库的RememberMe功能开发

基于数据库的RememberMe功能,我们需要配置数据库的持久化类bean。
JdbcTokenRepositoryImpl

.......
    @Bean
    public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();

        tokenRepository.setDataSource(dataSource);
        // 如果token表不存在,使用下面语句可以初始化该表;若存在,会报错。
        tokenRepository.setCreateTableOnStartup(true);
        return tokenRepository;
    }
.......

JdbcTokenRepositoryImpl继承JdbcDaoSupport,需要引入JdbcDaoSupport依赖,如下pom依赖

    <!--spring-boot-starter-jdbc自动配置-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
    <!--数据库驱动-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>

数据源bean
创建的JdbcTokenRepositoryImpl类需要set进去数据源对象,因此需要springboot集成DataSource。
配置数据源连接属性 application.properties。

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://bittechblog.com:3308/secu?useUnicode=true&characterEncoding=utf-8&useSSL=true
spring.datasource.username=root
spring.datasource.password=wanyang@wms
#\u5F00\u542FMybatis\u4E0B\u5212\u7EBF\u547D\u540D\u8F6C\u9A7C\u5CF0\u547D\u540D

将持久化工具类的bean注册到security中

  .and()
      .rememberMe()
      .tokenRepository(persistentTokenRepository())
      .tokenValiditySeconds(10)//有效时间为10s
//    .userDetailsService(userDetailsService())//userdetailservice使用了另外一种方式注册进去。

至此,基于数据库的rememberMe功能就开发完了, 对于开发者来说非常便捷。

3. 测试效果

访问http://localhost:8080/admin ,输入用户名密码root/666666后成功登入,查看数据库secu的表persistent_logins,有一条新的数据记录。每次重新登入都会有以条数据库记录。

alt

security保存的cookies设置的过期时间是30s,关闭浏览器时间过了30s后(准确的说是距离上次访问网站时间有30s间隔,每次访问都会刷新last_used字段值),从新打开浏览器就需要从新登入。

但是如果在30s内重新打开浏览器访问网站,则不需要重新登入。

以上就是基于数据库的RememberMe功能的测试效果,读者获取本文demo项目后,直接运行测试下效果。

4. 基于数据库的RememberMe功能缺点

对于互联网行业,用户基数往往是非常大的,活跃用户也是非常多,大量的活跃用户会同时发出高并发的访问请求,这种高并发请求如果全部发给数据库,极大可能会导致数据库宕机,影响整个网站的可用性。

这样的场景下,基于数据库来保存登入cookie数据是不可取的,那我们还有其他好的替代方案吗,能承担起这样的高并发请求吗?

这时候我们就需要将高并发的用户认证请求降级到缓存服务器,这样就能大大降低网站数据库层的压力。

完整的demo项目,请关注公众号“前沿科技bot“并发送"SEC-FOUR"获取。

alt

正文到此结束
本文目录