SpringSecurity5 记住我功能

SpringSecurity5 记住我功能
双木老林回到序章
前言
在使用其他网站的时候,像 Gitee、博客园啥的,上面都有一个“记住我”的复选框,点击之后,即时后面关掉浏览器,甚至关机后再重启,也不用登陆就可以直接用。spring security 自然也有实现了这个,本章就介绍这个。
代码实现
存储在内存
Security 配置类在 configure(HttpSecurity http) 方法中找个位置增加代码
1 | .rememberMe().and() |
前端网页增加记住我的复选框,关键是 name 值必须等于 remmember-me
1 | 记住密码: <input type="checkbox" name="remember-me" /><br /> |
如果想要更改这里的 name 值,配置类也需要对应的更新
1 | .rememberMe().rememberMeParameter("你想用的name值").and() |
在登陆的时候勾上复选框,即可实现。
下面是在浏览器检查元素中的部分截图。
也可以进检查元素 - Application - Cookies,查看到对应的cookie token,该 token 通过 Base64 加密
其中的 token 是 dXNlcjE6MTYyMTU3ODQzNDMwMjo2YWRmNWI5ZjEzM2QyNzdlYWYzM2Q2M2JmMDQ1NmRkYw,使用 Base64 解密后为 user1:1621578434302:6adf5b9f133d277eaf33d63bf0456ddc。
其中 user1 是登陆的账号;1621578434302 是过期时间,转换成能理解的格式是 2021-05-21,现在的时间是 2021-05-07,也就是默认是 14 天过期,需要重新登陆;6adf5b9f133d277eaf33d63bf0456ddc 是一串加密后的东东,直接给源码看吧。
1 | protected String makeTokenSignature(long tokenExpiryTime, String username, String password) { |
这部分源码下图的类中可以找到:
默认的 cookie-name 是 remember-me,默认的有效期是 14 天,这些都可以在配置类中配置更改:
1 | .rememberMe() |
这个的有效期不能设置为永久,从源码分析,当设置的值小于 0 的时候,会设置为 2 周,源码如下
1 |
|
源码位置:
数据库持久化
配置类
1 | .rememberMe() |
通过下面的这个方法可以看到,需要传入的是 org.springframework.security.web.authentication.rememberme.PersistentTokenRepository
1 | public RememberMeConfigurer<H> tokenRepository(PersistentTokenRepository tokenRepository) { |
进入 PersistentTokenRepository
1 | /** |
这个类的注释也简单明了的,这里是要实现持久化,所以选 JdbcTokenRepositoryImpl,进到这个类里面,可以看到建表以及增删改查的语句。
首先建议是直接拷建表语句去运行,因为它要生成表,你得设置 setCreateTableOnStartup(true) 才行,但是建完表得删除掉这句,因为语句是 create,所以当你第二次启动项目后,就会报错说该表已存在。
然后,默认的数据源是空,得赋值,所以得通过下面的写法实现:
1 |
|
分析
在介绍认证流程时,Emm,点进去直接滑到最底底,在处理成功/失败里,有那么一句 this.rememberMeServices.loginSuccess(request, response, authResult);
一层一层往上找,分别会找到如下
- org.springframework.security.web.authentication.RememberMeServices.loginSuccess
- org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices.loginSuccess
- org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices.onLoginSuccess( 内存 )
- org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices.onLoginSuccess( 持久化 )
- org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices.loginSuccess
这俩就大概跟你说了,你如果用 remember-me 登陆了,登陆成功后,会干些啥,大概就是该存库存库,该存 session 存 session,没啥好说的。另外退出登陆( /logout ),登陆失败,都是同样方法去找即可。
这里需要再介绍的是,当你关闭浏览器后,再次打开浏览器,访问依旧不用重新登陆是怎么实现的。
首先,就像登陆检验账号一样,都是通过过滤器实现的,而 remember-me 是 org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter 这个,大概核心的代码如下:
如果没法通过 SecurityContextHolder.getContext().getAuthentication() 获得当前的登陆账号信息,则取调用 autoLogin() 的方法
而 autoLogin() 干的事也简单,先去获得 cookie,然后通过 processAutoLoginCookie() 这个方法去上面最底层的那俩个类,对应到 processAutoLoginCookie() 进行登陆。























