认证方案对比:Session 方式 vs Token 方式

Spring Security 与 Sa-Token 两种认证方案的全面对比

一、Session 方式(Spring Security)

依赖

spring-boot-starter-security

核心类

类名说明
SecurityConfigSpring Security 配置(禁用 CSRF、放行请求、配置 Session 持久化)
WebConfig注册自定义拦截器
LoginCheckInterceptor拦截请求,校验登录状态
LoginServiceImpl登录时向 SecurityContextHolder 写入认证信息
SecurityUtil工具类,检查是否登录、获取当前用户
PermissionException自定义未登录异常
GlobalExceptionHandler全局异常处理,返回统一 JSON

登录流程

  1. 用户 POST /login/by/account
  2. LoginServiceImpl 创建 UsernamePasswordAuthenticationToken(account)
  3. SecurityContextHolder.getContext().setAuthentication(auth)
  4. 请求结束,SecurityContextHolderFilter 自动将认证信息保存到 HTTP Session
  5. 响应头 Set-Cookie: JSESSIONID=xxx

请求校验流程

  1. 请求携带 Cookie: JSESSIONID=xxx
  2. SecurityContextHolderFilter 从 Session 恢复认证信息到 SecurityContextHolder
  3. LoginCheckInterceptor 调用 SecurityUtil.isAuthenticated()
    • true → 放行,Controller 执行
    • false → 抛出 PermissionException → GlobalExceptionHandler 返回 Result.fail()
  4. 请求结束,SecurityContext 自动保存回 Session

获取当前用户

SecurityUtil.getCurrentUserId()

优点

缺点

二、Token 方式(Sa-Token)

依赖

sa-token-spring-boot3-starter

核心类

类名说明
WebConfig注册 Sa-Token 路由拦截器(一行配置)
LoginServiceImpl登录时调用 StpUtil.login(account) 生成 Token
GlobalExceptionHandler捕获 NotLoginException,返回统一 JSON

登录流程

  1. 用户 POST /login/by/account
  2. LoginServiceImpl 调用 StpUtil.login(account)
  3. Sa-Token 生成 Token,存入缓存(内存/Redis),建立 Token → 用户 映射
  4. 响应返回 Token 字符串

请求校验流程

  1. 请求携带请求头 satoken: xxx(或 Cookie: satoken=xxx)
  2. SaInterceptor 拦截器调用 StpUtil.checkLogin()
    • 从请求头/Cookie 获取 Token
    • 去缓存查 Token 对应的用户
    • 查到 → 放行,Controller 执行
    • 查不到/过期 → 抛出 NotLoginException → GlobalExceptionHandler 返回 Result.fail()

获取当前用户

StpUtil.getLoginId()

优点

缺点

三、核心差异总结

项目Session 方式Token 方式
登录凭证JSESSIONID Cookie自定义 Token 字符串
凭证存储位置服务端 HTTP Session缓存(内存/Redis)
凭证传递方式浏览器自动带 Cookie请求头或 Cookie(需配置)
集群部署需额外配置 Session 共享天然支持(集中存储)
配置复杂度5+ 个类1 个拦截器配置类
扩展功能需自行实现框架内置(踢人、权限等)

四、你的项目中两种方式的对应关系

Spring SecuritySa-Token
SecurityContextHolderStpUtil 内部缓存
UsernamePasswordAuthenticationStpUtil.login()
SecurityUtil.isAuthenticated()StpUtil.isLogin()
SecurityUtil.getCurrentUserId()StpUtil.getLoginId()
LoginCheckInterceptorSaInterceptor + SaRouter
PermissionExceptionNotLoginException
SecurityConfig(无需配置,引入依赖即用)