前言

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

参考目录

框架集成

基于 Sa-Token 最新版本

在这里插入图片描述

yaml 配置文件

这里需要关注的是两个 timeout 配置:
在这里插入图片描述

Sa-Token 配置 SaTokenConfig 注册拦截器

SaTokenConfig#addInterceptors
在这里插入图片描述
这里重点关注 StpUtil.checkLogin() 这个方法,其他的会放在后面扩展去简单进行讨论。

功能调用流程分析

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

从上面 SaTokenConfig#addInterceptors 开始进入,到 StpUtil#checkLogin
在这里插入图片描述
再深入一层,到 StpLogic#checkLogin
在这里插入图片描述
然后到今天的主角 StpLogic#getLoginId()

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

在这里插入图片描述
注释都写得很明白了,先是进行各种判断,如果全部通过了,来到最后两个方法:

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

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

在这里插入图片描述

1.1.1、计算过期时间 StpLogic#getTokenActivityTimeoutByToken

在这里插入图片描述

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

在这里插入图片描述
全局异常处理 GlobalExceptionHandler#handleNotLoginException
在这里插入图片描述
控制台输出:
在这里插入图片描述

1.3、未过期,完成验证

未过期则打上检查标记,完成验证。
在这里插入图片描述

2、续签 StpLogic#updateLastActivityToNow

在这里插入图片描述
续签实际上就是更新缓存中的最后操作时间为当前时间。
在这里插入图片描述

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

在这里插入图片描述
至此,拦截器登录检查完成。

扩展分析

扩展1、关于手动续签

图源 Sa-Token 官方文档:
这里是引用

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

值得注意的是,手动续签的时候如果判断 token 临时有效期过期了,依然可以续签成功,因为续签方法是单独的,并没有判断 token 的状态。换句话说,如果捕获到 NotLoginException 异常,那么可以在 catch 中进行手动续签。
在这里插入图片描述
这样的话依然可以返回正确结果,而非抛出 401 异常。

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

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

这里是引用
在这里插入图片描述

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

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

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

先从 1.1 方法 StpLogic#checkActivityTimeout 回溯:
调用方法 SaStorage storage = SaHolder.getStorage();
在这里插入图片描述
SaManager#getSaTokenContextOrSecond
在这里插入图片描述
Sa-Token 上下文处理器 SaTokenContext
在这里插入图片描述
关于 SaTokenContext 官方文档 也有作介绍:

在这里插入图片描述

最后一段话很重要,继续找源头:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
至此可知 SaStorage 的完整创建流程。

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

在之前登录接口中也有用到这个对象,因此可以在这里也整理一下。
StpLogic#login
在这里插入图片描述
StpLogic#setTokenValueToStorage
在这里插入图片描述

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

在配置拦截器时需要排除指定的路径,如下:
在这里插入图片描述
参考 框架wiki ,主要有两个途径:

  1. yaml 配置文件
    在这里插入图片描述
  2. 配置 @Anonymous 注解
    在这里插入图片描述

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

ExcludeUrlProperties
在这里插入图片描述
这个类是懒加载方式,第一次请求的时候才会将所有需要过滤的请求放到数组 excludes 中(RequestMappingHandlerMapping 能获取到容器中所有请求的方法),并且只会加载一次。

这里会对 /demo/demo/{id} 这种路径进行替换变成 /demo/demo/*
在这里插入图片描述
在这里插入图片描述
但是要注意路径要唯一,否则会把同级别其他路径一起进行过滤:

在这里插入图片描述

Logo

快速构建 Web 应用程序

更多推荐