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

一、最简实践

其实实现这个功能非常简单,只需要我们在重写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周内免登录。

二、实现原理

很多朋友可能看了上面的实现过程心里都犯懵,这样就实现了?下面和大家说明一下这过程中间,都做了哪些事情。

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

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

RememberMeAuthenticationFilter在Spring Security过滤器链中处于整体偏后的位置,所以只有当各种传统的登录方式都无法完成验证的情况下,才走RememberMeAuthenticationFilter,这也是符合实际需求的。

三、个性化配置

在实际的开发过程中,我们还可以根据需求做一些个性化的设置,如下:

.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。

四、token数据库存储方式

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

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

上图是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())

期待您的关注

Spring Security框架下实现两周内自动登录"记住我"功能的更多相关文章

  1. JS-两周内自动登录功能

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  2. 在Spring Security框架下JWT的实现细节原理

    一.回顾JWT的授权及鉴权流程 在笔者的上一篇文章中,已经为大家介绍了JWT以及其结构及使用方法.其授权与鉴权流程浓缩为以下两句话 授权:使用可信用户信息(用户名密码.短信登录)换取带有签名的JWT令 ...

  3. Spring Security框架下Restful Token的验证方案

    项目使用Restful的规范,权限内容的访问,考虑使用Token验证的权限解决方案. 验证方案(简要概括): 首先,用户需要登陆,成功登陆后返回一个Token串: 然后用户访问有权限的内容时需要上传T ...

  4. 在Spring Boot框架下使用WebSocket实现聊天功能

    上一篇博客我们介绍了在Spring Boot框架下使用WebSocket实现消息推送,消息推送是一对多,服务器发消息发送给所有的浏览器,这次我们来看看如何使用WebSocket实现消息的一对一发送,模 ...

  5. Spring Security框架中踢人下线技术探索

    1.背景 在某次项目的开发中,使用到了Spring Security权限框架进行后端权限开发的权限校验,底层集成Spring Session组件,非常方便的集成Redis进行分布式Session的会话 ...

  6. Servlet课程0426(十一)Servlet Cookie实现两周内不用重复登录

    Welcome.java //登录界面 package com.tsinghua; import javax.servlet.http.*; import java.io.*; import java ...

  7. 在Spring Boot框架下使用WebSocket实现消息推送

    Spring Boot的学习持续进行中.前面两篇博客我们介绍了如何使用Spring Boot容器搭建Web项目(使用Spring Boot开发Web项目)以及怎样为我们的Project添加HTTPS的 ...

  8. Spring Boot 框架下使用MyBatis访问数据库之基于XML配置的方式

    MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以使用简单的 XML ...

  9. Spring Security框架进阶、自定义登录

      1.Spring Security框架进阶 1.1 Spring Security简介 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安 ...

随机推荐

  1. Intellij IDEA 常用的插件 建议全装

    介绍几个常用的插件 Alibaba Java Coding Guidelines https://plugins.jetbrains.com/plugin/10046-alibaba-java-cod ...

  2. 疯狂Java:突破程序员基本功的16课-李刚编著 学习笔记(未完待续)

    突破程序员基本功(16课) 数组 静态语言: 在编译的时候就能确定数据类型的语言,大多静态语言要求在使用变量之前必须声明数据类型(少数具有强推导能力的现代语言不用) 动态语言: 在程序运行时确定数据类 ...

  3. windows设置本地域名解析

    1.首先找到host文件:C:\Windows\System32\drivers\etc 2.打开host文件: # Copyright (c) 1993-2009 Microsoft Corp. # ...

  4. Java多线程编程(七)线程状态、线程组与异常处理

    一.线程的状态 线程对象在不同的运行时期有不同的状态,状态信息就存在于State枚举类中. 调用与线程有关的方法后,会进入不同的线程状态,这些状态之间某些是可双向切换的,比如WAITING和RUNNI ...

  5. Unity C#数据持久化与xml

    最近工作需要用到数据持久化,所以在此分享一下,通过查阅资料,数据持久化大体都是通过xml或者json来进行的.unity为我们自定义了数据持久化方法,但是比较局限,还需要自己来完成数据持久化方法. ( ...

  6. 练习Markdown基本语法

    这是一级标题 二级标题 三级标题 我就说一点(数字+英文句点.) 第二 在行首增加*或-,就会有下面的效果 嘿 嘿 嘿 这一部分是插入图片和引用 插入图片 用感叹号+[]+括号 直接复制粘贴~ 引用 ...

  7. opacity层叠问题

    使用了position属性值为 absolute.relative 的层,将会比普通层更高层次.使用了小于1的opacity属性的层,也比普通层更高层次并且和指定 position 的层同层,但是不支 ...

  8. npm 学习笔记

    一.介绍 1.是什么 npm 全称是 Node Package Manager,即 Node 包管理工具. 但是发展到后来,并不仅是适用于 node.js 的包. 所以现在看 node_modules ...

  9. CSP2019知识点整理

    也算是接下来二十天的复习计划吧 仅止于联赛难度左右 基础算法 字符串 char[] cstring memset() 输入无& gets(), fgets(stdin, ,); strcmp, ...

  10. nginx篇高级用法之基于TCP/UDP的四层调度

    nginx 从1.9版本开始支持基于TCP/UDP的四层调度,在编译nginx时使用--with-stream开启该模块 支持TCP/UDP调度时,支持给所有的软件做调度器,例如:nfs smb ft ...