Appearance
Spring 登录鉴权怎么设计:拦截器、Token、上下文传递分别负责什么
很多 Spring 项目做登录鉴权时,一开始都很简单:
- 登录后发个 token
- 每次请求带上 token
- 服务端解析一下
但一到项目变大,就会开始乱:
- 哪一层校验登录
- 哪一层校验权限
- 当前用户信息往哪儿放
先说结论
更稳妥的设计通常是:
- 登录态校验放在统一入口
- 权限判断按资源和业务边界拆开
- 当前用户上下文只做“透传”,不要滥用
- 鉴权链路和业务逻辑分离
一、拦截器最适合做什么
拦截器更适合处理这些事情:
- 判断请求是否需要登录
- 解析 token
- 把当前用户信息放进上下文
它不太适合承载特别复杂的业务权限判断。
因为一旦权限逻辑全堆在拦截器里,后面会越来越难维护。
二、登录态和权限不是一回事
这个区分很重要。
登录态在回答:
- 你是谁
- 你是否已经登录
权限在回答:
- 你能不能做这件事
很多项目把这两件事混在一起,最后会导致:
- 某些接口难扩展
- 角色变多后逻辑爆炸
三、当前用户上下文为什么容易出问题
因为它通常会搭配:
ThreadLocal- 拦截器
- 异步线程池
一旦线程复用或异步调用没有处理好,就容易出现:
- 用户信息串请求
- 上下文丢失
所以当前用户上下文最好只在同步请求链路里谨慎使用。
四、一个更实用的分层方式
1. 网关或入口层
可以先做基础认证校验和非法请求拦截。
2. 应用层拦截器
负责:
- 解析 token
- 识别当前用户
- 设置上下文
3. 业务层
负责:
- 判断当前用户能不能操作该资源
- 是否满足更细的业务权限规则
五、最容易踩的坑
1. 把权限判断全写在 if-else 里
后面角色一多,很快失控。
2. 在异步线程里直接拿当前用户上下文
这很容易埋 ThreadLocal 的坑。
3. token 只校验是否存在,不校验状态
过期、登出、禁用这些状态最好有明确处理。
六、什么时候该考虑更完整的权限模型
当项目开始出现这些情况时,就要提升设计了:
- 后台角色变多
- 菜单和接口权限开始分开
- 不同组织、租户、数据范围权限出现
这时“简单拦截器 + 简单角色判断”通常就不够了。
一句话总结
Spring 登录鉴权设计真正重要的,不是“能不能拦住未登录请求”,而是把:
- 登录态识别
- 权限判断
- 上下文传递
这三件事拆清楚。