「这是我参与11月更文挑战的第11天,活动详情查看:2021最后一次更文挑战」。
一、自动登录
自动登录实质上是指将用户的登录信息保存在用户浏览器cookie中,当用户下次访问时,自动实现校验并建立登录状态的一种机制。
处于安全考虑会将用户信息先加密,再存于cookie
中。
Spring Security提供了两种非常好的令牌
- 用散列算法加密用户登录信息并生成令牌
- 数据库等持久性数据存储机制用的持久化令牌
1. 散列加密方案
修改配置configure()(基于过滤器实现图形验证码代码修改)
1 | java复制代码@Autowired |
在自定义页面中添加remember-me checkbox
注意: name必须为remember-me
1 | html复制代码<div> |
- 启动项目
- 访问api:
http://localhost:8080/user/api/hi
- 勾选记住我
- 登录
- F12打开控制台查看cookie
在源码中可以找到与之对应代码
1 | java复制代码public abstract class AbstractRememberMeServices implements RememberMeServices, InitializingBean, LogoutHandler { |
Spring Security每次登录成功之后会更新令牌
1 | java复制代码public void onLoginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication) { |
加密部分
1 | java复制代码 protected String makeTokenSignature(long tokenExpiryTime, String username, String password) { |
key
默认情况下是随机生成的
1 | java复制代码private String getKey() { |
- 这样会导致每次重启项目都会重新生成key,使之前浏览器保存的全部失效。
- 另外当多实例部署时由于实例之间的key都不相同,所以当访问另一个实例时自动登录策略也会失效
- 合理的做法是指定key
这种方式实现简单,无需花费服务器资源存储自动登录的相关信息。但是存在cookie被盗风险。
2. 持久化令牌方案
相比于散列加密方案采用了更加严谨的安全设计
核心的两个值(都是采用MD5
加密过的随机字符串)
- series 仅在用户使用密码重新登录时更新
- token 在每一个新的session中都重新生成
这样做的的好处
- 解决了一个令牌在多端登录的情况
- 同时校验series和token,如果令牌被盗,当非法登录时,会刷新token的值,这样合法用户自动登录的时候,校验series一样,但是token不一样,可以推测令牌被盗用。
Spring Security使用PersistentRememberMeToken来表明一个验证实体
1 | java复制代码public class PersistentRememberMeToken { |
- 在数据库中建一张persistent_logins表(存储自动登录信息的表)
1 | mysql复制代码CREATE TABLE `persistent_logins` ( |
- 定制tokenRepository
配置中需要传入一个PersistentTokenRepository实例,此接口定义了持久化令牌的一些必要方法
1 | java复制代码public interface PersistentTokenRepository { |
可以利用自带的实现类JdbcTokenRepositoryImpl实现持久化,为其指定DataSource
1 | java复制代码@Autowired |
- 启动项目
- 访问api:
http://localhost:8080/user/api/hi
- 登录
- 查看表中自动插入了验证数据
- 重启项目
- 访问api:
http://localhost:8080/user/api/hi
- 自动登录
和我们预料的一样,series不变,验证自动登录成功后刷新token的值
这种方式同样存在令牌被盗的风险
二、注销登录
1. 系统自带
Spring Security自带注销登录逻辑,默认请求
/logout
,注销后
HttpSession失效、清空已配置的Remember-me验证,以及清空SecurityContextHolder
2.自行配置
根据自己需要,编写退出登录逻辑,清除登录的一系列信息。
本文转载自: 掘金