1. 若依框架的登录与Token生成:不只是登录那么简单
很多刚开始用若依框架的朋友,可能觉得登录就是个验证用户名密码的事儿,拿到一个Token就完事了。我以前也这么想,直到在一个用户量不小的项目里,老有用户抱怨“怎么用着用着就突然要我重新登录了”,这才开始深挖若依的登录和Token机制。我发现,若依在这块的设计,尤其是Token的刷新,考虑得非常周到,它把登录、认证、会话维持这一整套流程,做得既安全又对用户体验友好。今天,我就结合自己踩过的坑和调试经验,跟你详细聊聊若依里Token刷新机制是怎么设计和实现的,保证你能看懂,还能用上。
简单来说,若依的登录流程可以分成两大块:一块是登录校验和信息处理,另一块是Token的生成与后续的持续维护。第一块大家容易理解,就是检查你是张三还是李四。而第二块,也就是Token刷新机制,才是保证你登录后能长时间顺畅操作、无需反复重登的关键。这背后是一套结合了JWT(JSON Web Token)、Redis缓存和Spring Security过滤器链的“组合拳”。我们不仅要知道怎么登录,更得明白系统是怎么在背后悄无声息地帮你“续费”登录状态的。
先看登录入口。在若依里,登录的核心方法是 SysLoginService 里的 login 方法。这个过程远不止比对密码。它首先会进行验证码校验(防止暴力破解),然后做一些登录前置检查。最关键的一步是调用了 authenticationManager.authenticate() 方法。这里有个细节:若依巧妙地把用户名密码封装进了一个 UsernamePasswordAuthenticationToken 对象,然后把它放到了一个叫 AuthenticationContextHolder 的类里。这个 AuthenticationContextHolder 内部用的是 ThreadLocal,你可以把它理解为一个“线程保险箱”,它能在同一个线程处理的整个请求生命周期内,临时存放认证信息,确保后续步骤能拿到当前登录用户的信息,用完之后又会被清理掉,避免内存泄漏。
认证成功后,系统会记录登录日志、更新用户最后登录时间,然后重头戏来了——调用 tokenService.createToken(loginUser) 来生成Token。这个生成过程很有意思,它采用了“双Token”策略。首先,它用 IdUtils.fastUUID() 生成一个全局唯一的字符串,我们姑且叫它 “内部Token” 或 “UUID Token”。这个字符串会被设置到 LoginUser 对象里,然后,以这个UUID为Key的一部分,将整个 LoginUser 对象(包含用户ID、权限、登录时间等信息)存入Redis。最后,再用JWT库,将这个UUID作为JWT的一个声明(claim)生成一个 “JWT Token”,这个才是最终返回给前端、放在请求头里的那个令牌。
public String createToken(LoginUser loginUser) {
// 1. 生成一个UUID作为内部令牌标识
String token = IdUtils.fastUUID();
loginUser.setToken(token);
setUserAgent(loginUser);
// 2. 刷新Token(核心:将用户信息存入Redis,并设置过期时间)
refreshToken(loginUser);
// 3. 将UUID放入JWT的声明中,生成最终的JWT Token
Map<String, Object> claims = new HashMap<>();
claims.put(Constants.LOGIN_USER_KEY, token);
return createToken(claims); // 调用JWT生成方法
}
为什么要这么麻烦,搞两层?直接用一个JWT存所有信息不行吗?这是若依设计的一个精妙之处。JWT本身是自包含的,一旦签发,在有效期内无法直接使其失效。如果把用户详细信息和权限都塞进JWT,想在中途强制某个用户下线(比如管理员踢人)或者实时更新用户权限,就会非常困难。而若依的方案里,JWT里只存了一个对Redis中数据的“引用”(即那个UUID)。真正的用户数据在Redis里。这样,我们想让某个Token失效,只需要删除Redis里对应的Key;想更新用户信息,也只需要更新Redis里的数据即可,实现了灵活的会话管理。
2. Token刷新的核心引擎:refreshToken 与 verifyToken
理解了Token的生成,我们再来看看若依是如何让这个Token“活”得更久的。这就是


335

被折叠的 条评论
为什么被折叠?



