前几天在群里面聊到关于 token 续签的问题,这个在 Sa-Token 官方文档也有相应的说明,这篇文章还是从源码角度去看看到底做了什么。
SaTokenConfig
注册拦截器SaTokenConfig#addInterceptors
这里重点关注 StpUtil.checkLogin()
这个方法,其他的会放在后面扩展去简单进行讨论。
关于 StpUtil.checkLogin()
底层的调用过程比较简单容易理解,所以没有画流程图。
从上面 SaTokenConfig#addInterceptors
开始进入,到 StpUtil#checkLogin
:
再深入一层,到 StpLogic#checkLogin
:
然后到今天的主角 StpLogic#getLoginId()
。
StpLogic#getLoginId()
注释都写得很明白了,先是进行各种判断,如果全部通过了,来到最后两个方法:
checkActivityTimeout
检查的值对应的是配置文件中的 activity-timeout
属性值。activity-timeout
属性值。StpLogic#checkActivityTimeout
StpLogic#getTokenActivityTimeoutByToken
NotLoginException
(Token已过期)
全局异常处理 GlobalExceptionHandler#handleNotLoginException
:
控制台输出:
StpLogic#updateLastActivityToNow
官方提供了手动续签的方法,底层也是调用了上面续签的方法 StpLogic#updateLastActivityToNow
。
值得注意的是,手动续签的时候如果判断 token 临时有效期过期了,依然可以续签成功,因为续签方法是单独的,并没有判断 token 的状态。换句话说,如果捕获到 NotLoginException
异常,那么可以在 catch 中进行手动续签。
这样的话依然可以返回正确结果,而非抛出 401 异常。
关于这个问题,我询问了一下 狮子大佬 ,他说得比较详细,我直接贴出来:
SaStorage
在前面 1.1、检查 token 是否已经临时过期
里面的方法有用到这个对象(存取检查标记),所以拿出来说一下。
通过查找源码可以得知这个对象是一开始被 Spring 加载到容器中的,本质上就是一个 Servletcontext
对象。
先从 1.1 方法 StpLogic#checkActivityTimeout
回溯:
调用方法 SaStorage storage = SaHolder.getStorage();
SaManager#getSaTokenContextOrSecond
Sa-Token 上下文处理器 SaTokenContext
关于 SaTokenContext
官方文档 也有作介绍:
最后一段话很重要,继续找源头:
至此可知 SaStorage
的完整创建流程。
SaStorage
使用在之前登录接口中也有用到这个对象,因此可以在这里也整理一下。
StpLogic#login
StpLogic#setTokenValueToStorage
ExcludeUrlProperties
在配置拦截器时需要排除指定的路径,如下:
参考 框架wiki ,主要有两个途径:
第一种比较简单,直接读取配置文件,我们聊聊第二种。
ExcludeUrlProperties
这个类是懒加载方式,第一次请求的时候才会将所有需要过滤的请求放到数组 excludes
中(RequestMappingHandlerMapping
能获取到容器中所有请求的方法),并且只会加载一次。
这里会对 /demo/demo/{id}
这种路径进行替换变成 /demo/demo/*
。
但是要注意路径要唯一,否则会把同级别其他路径一起进行过滤: