【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)

文章目录

    • 前言
    • 参考目录
    • 框架集成
      • 基于 Sa-Token 最新版本
      • yaml 配置文件
      • Sa-Token 配置 `SaTokenConfig` 注册拦截器
    • 功能调用流程分析
      • 1、获取当前会话账号id `StpLogic#getLoginId()`
      • 1.1、检查 token 是否已经临时过期 `StpLogic#checkActivityTimeout`
      • 1.1.1、计算过期时间 `StpLogic#getTokenActivityTimeoutByToken`
      • 1.2、已过期抛出异常 `NotLoginException` (Token已过期)
      • 1.3、未过期,完成验证
      • 2、续签 `StpLogic#updateLastActivityToNow`
      • 3、完成所有步骤,返回 loginId
    • 扩展分析
      • 扩展1、关于手动续签
      • 扩展2、为什么需要两个 timeout ?
      • 扩展3、关于 [存储器] 包装类 `SaStorage`
      • 扩展4、登录接口中 `SaStorage` 使用
      • 扩展5、设置注解允许匿名访问的url `ExcludeUrlProperties`

前言

前几天在群里面聊到关于 token 续签的问题,这个在 Sa-Token 官方文档也有相应的说明,这篇文章还是从源码角度去看看到底做了什么。

参考目录

  • Sa-Token 官方文档:Token有效期详解

框架集成

基于 Sa-Token 最新版本

在这里插入图片描述

yaml 配置文件

这里需要关注的是两个 timeout 配置:
【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)_第1张图片

Sa-Token 配置 SaTokenConfig 注册拦截器

SaTokenConfig#addInterceptors
【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)_第2张图片
这里重点关注 StpUtil.checkLogin() 这个方法,其他的会放在后面扩展去简单进行讨论。

功能调用流程分析

关于 StpUtil.checkLogin() 底层的调用过程比较简单容易理解,所以没有画流程图。

从上面 SaTokenConfig#addInterceptors 开始进入,到 StpUtil#checkLogin
【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)_第3张图片
再深入一层,到 StpLogic#checkLogin
【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)_第4张图片
然后到今天的主角 StpLogic#getLoginId()

1、获取当前会话账号id StpLogic#getLoginId()

【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)_第5张图片
注释都写得很明白了,先是进行各种判断,如果全部通过了,来到最后两个方法:

  1. 检查是否临时过期
    这里的checkActivityTimeout 检查的值对应的是配置文件中的 activity-timeout 属性值。
  2. 判断是否自动续签
    续签的时间也是对应的是配置文件中的 activity-timeout 属性值。

1.1、检查 token 是否已经临时过期 StpLogic#checkActivityTimeout

【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)_第6张图片

1.1.1、计算过期时间 StpLogic#getTokenActivityTimeoutByToken

【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)_第7张图片

1.2、已过期抛出异常 NotLoginException (Token已过期)

【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)_第8张图片
全局异常处理 GlobalExceptionHandler#handleNotLoginException
【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)_第9张图片
控制台输出:
【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)_第10张图片

1.3、未过期,完成验证

未过期则打上检查标记,完成验证。
【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)_第11张图片

2、续签 StpLogic#updateLastActivityToNow

【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)_第12张图片
续签实际上就是更新缓存中的最后操作时间为当前时间。
【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)_第13张图片

3、完成所有步骤,返回 loginId

【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)_第14张图片
至此,拦截器登录检查完成。

扩展分析

扩展1、关于手动续签

图源 Sa-Token 官方文档:
【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)_第15张图片

官方提供了手动续签的方法,底层也是调用了上面续签的方法 StpLogic#updateLastActivityToNow

值得注意的是,手动续签的时候如果判断 token 临时有效期过期了,依然可以续签成功,因为续签方法是单独的,并没有判断 token 的状态。换句话说,如果捕获到 NotLoginException 异常,那么可以在 catch 中进行手动续签。
【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)_第16张图片
这样的话依然可以返回正确结果,而非抛出 401 异常。

扩展2、为什么需要两个 timeout ?

关于这个问题,我询问了一下 狮子大佬 ,他说得比较详细,我直接贴出来:

【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)_第17张图片
【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)_第18张图片

扩展3、关于 [存储器] 包装类 SaStorage

在前面 1.1、检查 token 是否已经临时过期 里面的方法有用到这个对象(存取检查标记),所以拿出来说一下。

通过查找源码可以得知这个对象是一开始被 Spring 加载到容器中的,本质上就是一个 Servletcontext 对象。

先从 1.1 方法 StpLogic#checkActivityTimeout 回溯:
调用方法 SaStorage storage = SaHolder.getStorage();
【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)_第19张图片
SaManager#getSaTokenContextOrSecond
【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)_第20张图片
Sa-Token 上下文处理器 SaTokenContext
【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)_第21张图片
关于 SaTokenContext 官方文档 也有作介绍:

【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)_第22张图片

最后一段话很重要,继续找源头:
【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)_第23张图片
【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)_第24张图片
【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)_第25张图片
至此可知 SaStorage 的完整创建流程。

扩展4、登录接口中 SaStorage 使用

在之前登录接口中也有用到这个对象,因此可以在这里也整理一下。
StpLogic#login
【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)_第26张图片
StpLogic#setTokenValueToStorage
【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)_第27张图片

扩展5、设置注解允许匿名访问的url ExcludeUrlProperties

在配置拦截器时需要排除指定的路径,如下:
【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)_第28张图片
参考 框架wiki ,主要有两个途径:

  1. yaml 配置文件
    【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)_第29张图片
  2. 配置 @Anonymous 注解
    【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)_第30张图片

第一种比较简单,直接读取配置文件,我们聊聊第二种。

ExcludeUrlProperties
【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)_第31张图片
这个类是懒加载方式,第一次请求的时候才会将所有需要过滤的请求放到数组 excludes 中(RequestMappingHandlerMapping 能获取到容器中所有请求的方法),并且只会加载一次。

这里会对 /demo/demo/{id} 这种路径进行替换变成 /demo/demo/*
【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)_第32张图片
【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)_第33张图片
但是要注意路径要唯一,否则会把同级别其他路径一起进行过滤:

【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)_第34张图片

你可能感兴趣的:(框架学习,-,若依,/,RuoYi-Vue-Plus,#,Sa-Token,RuoYi-Vue-Plus,Sa-Token,java)