Sa-Token PHP 使用手册
Sa-Token PHP 使用手册
RichSa-Token PHP 完全开发手册(ThinkPHP 8 版)
框架版本: ThinkPHP 8.0+
项目版本: 基于 pohoc/sa-token 最新源码
PHP 版本: PHP >= 8.1
目录
- 一、框架概述与核心概念
- 二、环境要求与安装部署
- 三、四种部署模式详解
- 四、登录认证系统
- 五、权限认证系统
- 六、Cookie 与 Session 管理
- 七、注解式鉴权
- 八、路由拦截鉴权
- 九、SSO 单点登录
- 十、OAuth2.0 认证
- 十一、安全防护体系
- 十二、高级功能
- 十三、异常处理体系
- 十四、完整配置参考
- 十五、项目结构与部署指南
- 十六、API 快速参考手册
- 十七、常见问题与解决方案
一、框架概述与核心概念
1.1 什么是 Sa-Token?
Sa-Token 是一个轻量级、功能完备的权限认证框架,以简单、优雅的方式完成系统的权限认证部分。与 SpringSecurity、Shiro 等传统框架相比,Sa-Token 的 API 设计更加简洁——绝大多数功能都能用一行代码解决。
核心设计理念:
- 简单:登录认证只需
StpUtil::login(10001),权限校验只需StpUtil::checkPermission('user:add') - 灵活:支持多账号体系、多存储引擎、多部署模式
- 安全:内置防暴力破解、IP 异常检测、设备管理、敏感操作验证
- 全面:从登录认证到权限管理,从 SSO 到 OAuth2.0,从 Cookie 到 Session,覆盖完整认证链路
1.2 四种部署模式完整对比
| 特性 | 单应用+Redis | 单应用+内存 | 多应用+Redis | 多应用+内存 |
|---|---|---|---|---|
| 适用场景 | 生产环境、高并发 | 开发测试、低并发 | 微服务、分布式 | 小型多模块项目 |
| 数据持久化 | ✅ Redis 持久化 | ❌ 重启丢失 | ✅ Redis 持久化 | ❌ 重启丢失 |
| 分布式支持 | ✅ 支持 | ❌ 不支持 | ✅ 支持 | ❌ 不支持 |
| 性能 | 高 | 非常高 | 高 | 非常高 |
| 内存占用 | 低 | 高 | 低 | 高 |
| 扩展性 | 优秀 | 一般 | 优秀 | 一般 |
| 部署复杂度 | 中等 | 低 | 中等 | 低 |
| 推荐场景 | 生产环境 | 开发/测试 | 微服务架构 | 小型项目 |
1.3 核心功能矩阵
| 类别 | 功能 | 说明 |
|---|---|---|
| 登录认证 | 单端登录 | 一个账号只能在一个设备登录 |
| 多端登录 | 一个账号可在多个设备同时登录 | |
| 同端互斥登录 | 同一设备类型只能登录一个 | |
| 七天内免登录 | 记住我功能,延长登录有效期 | |
| 踢人下线 | 强制指定用户下线 | |
| 账号封禁 | 禁止账号登录指定时长 | |
| 权限认证 | 权限校验 | 判断用户是否拥有某权限 |
| 角色校验 | 判断用户是否拥有某角色 | |
| 二级认证 | 敏感操作二次身份验证 | |
| 身份切换 | 临时切换到其他用户身份 | |
| 注解式鉴权 | 通过注解声明鉴权规则 | |
| Cookie 管理 | 自动写入 | 登录后自动写入 Cookie |
| 自动读取 | 请求时自动读取 Cookie | |
| 安全配置 | Secure/HttpOnly/SameSite | |
| 跨域共享 | 多域名间共享 Cookie | |
| Session 会话 | 账号 Session | 同一账号所有设备共享 |
| Token Session | 仅当前 Token 独享 | |
| 自定义 Session | 任意 Key 的 Session | |
| 自动清理 | 过期 Session 自动清理 | |
| Token 安全 | 多种风格 | uuid/simple-uuid/random-32/random-64/random-128/tik |
| Token 前缀 | 如 Bearer 前缀 | |
| Token 加密 | AES-256/SM4 加密 | |
| 指纹绑定 | IP+UA 防止 Token 盗用 | |
| 黑名单 | 手动拉黑 Token | |
| Refresh Token | 双 Token 机制 | AccessToken + RefreshToken |
| Token 轮换 | 刷新时自动轮换 | |
| 无感刷新 | 客户端无感知刷新 Token | |
| SSO 单点登录 | 四种模式 | 同域/跨域/前后端分离/无 SDK |
| OAuth2.0 | 四种授权模式 | 授权码/隐藏式/密码/客户端凭证 |
| OpenID Connect | 支持 OIDC 协议 | |
| 安全防护 | 防暴力破解 | 登录失败次数限制 |
| IP 异常检测 | 异地登录检测 | |
| 设备管理 | 登录设备记录与管理 | |
| 敏感操作验证 | OTP/安全令牌 |
1.4 核心术语详解
| 术语 | 说明 |
|---|---|
StpUtil |
静态工具类,提供所有认证 API |
StpLogic |
逻辑类,支持多账号体系隔离 |
SaRouter |
路由匹配器,用于 URL 拦截鉴权 |
Token |
身份凭证,由框架生成和管理 |
LoginId |
登录标识,通常为用户 ID |
SaTokenDao |
数据持久层接口,负责所有会话数据的底层写入和读取 |
Session |
会话对象,存储当前用户的状态数据 |
Cookie |
客户端存储 Token 的机制 |
SaManager |
管理 Sa-Token 所有全局组件的核心类 |
StpInterface |
自定义权限加载接口,需开发者实现 |
二、环境要求与安装部署
2.1 环境要求
1 | PHP >= 8.1 |
2.2 创建项目
1 | # 创建单应用项目 |
2.3 安装 Sa-Token
1 | composer require pohoc/sa-token |
2.4 安装 Redis 扩展(Redis 模式必需)
1 | # 方式一:使用 predis(推荐) |
2.5 文件清单(使用前需创建)
| 文件路径 | 说明 | 优先级 |
|---|---|---|
config/sa_token.php |
主配置文件 | ✅ 必须 |
config/sa_token_sso.php |
SSO 配置(使用 SSO 时) | ⚠️ 按需 |
config/sa_token_oauth2.php |
OAuth2.0 配置(使用 OAuth2 时) | ⚠️ 按需 |
app/service/PermissionService.php |
权限数据提供者 | ✅ 必须 |
app/middleware/SaTokenMiddleware.php |
鉴权中间件 | ✅ 推荐 |
app/exception/Handler.php |
异常处理器 | ✅ 推荐 |
app/provider/SaTokenProvider.php |
服务提供者 | ✅ 推荐 |
config/middleware.php |
中间件注册配置 | ✅ 必须 |
config/service.php |
服务提供者注册 | ✅ 必须 |
三、四种部署模式详解
3.1 单应用 + Redis 模式
3.1.1 场景说明
适用于生产环境的单体应用,使用 Redis 作为存储介质,支持数据持久化、分布式部署、高并发场景。Token 会话数据存储在 Redis 中,应用重启后用户无需重新登录。
3.1.2 目录结构
1 | tp8-sa-token/ |
3.1.3 创建配置文件 config/sa_token.php
1 |
|
3.1.4 创建权限数据提供者 app/service/PermissionService.php
1 |
|
3.1.5 创建服务提供者 app/provider/SaTokenProvider.php
1 |
|
3.1.6 创建中间件 app/middleware/SaTokenMiddleware.php
1 |
|
3.1.7 注册服务提供者 config/service.php
1 |
|
3.1.8 注册中间件 config/middleware.php
1 |
|
3.1.9 单应用路由 route/app.php
1 |
|
3.1.10 环境变量配置 .env
1 | # Redis 配置 |
3.1.11 创建数据库表结构
1 | -- 用户表 |
3.2 单应用 + 内存模式
3.2.1 场景说明
适用于开发测试环境或低并发的小型项目,使用内存作为存储介质。特点是:
- 无需 Redis:减少依赖,降低部署复杂度
- 高性能:纯内存操作,读写速度最快
- 数据易失:应用重启后所有 Token 会话丢失,用户需重新登录
- 不支持分布式:多实例部署时无法共享会话
3.2.2 配置文件差异
1 | // config/sa_token.php |
3.2.3 服务提供者差异
1 | // app/provider/SaTokenProvider.php |
3.2.4 环境变量配置 .env
1 | # 内存模式不需要 Redis 配置 |
3.2.5 内存模式注意事项
1 | // ========== 内存模式特点 ========== |
3.3 多应用 + Redis 模式
3.3.1 场景说明
适用于微服务架构或模块化中大型项目,多个应用共享 Redis 存储,实现:
- Token 共享:用户在一个应用登录后,其他应用自动识别
- 分布式部署:每个应用可独立部署、独立扩展
- 数据持久化:Redis 持久化存储,应用重启会话不丢失
- 应用隔离:通过 Redis key 前缀实现各应用数据隔离
3.3.2 启用多应用模式
1 | # 安装多应用扩展 |
3.3.3 目录结构
1 | tp8-sa-token/ |
3.3.4 全局基础配置 config/sa_token.php
1 |
|
3.3.5 API 应用专属配置 app/api/config/sa_token.php
1 |
|
3.3.6 Admin 应用专属配置 app/admin/config/sa_token.php
1 |
|
3.3.7 公共服务提供者 app/common/provider/SaTokenProvider.php
1 |
|
3.3.8 公共中间件 app/common/middleware/SaTokenMiddleware.php
1 |
|
3.3.9 多应用路由配置
API 应用路由 app/api/route/app.php
1 |
|
Admin 应用路由 app/admin/route/app.php
1 |
|
3.3.10 多应用 Redis 隔离验证
1 | // 不同应用使用不同的 Redis key 前缀 |
3.4 多应用 + 内存模式
3.4.1 场景说明
适用于小型多模块项目或开发测试环境的多应用场景:
- 多应用结构:模块化分离,如 API、Admin、Web 分离
- 无需 Redis:减少依赖,快速搭建
- 数据隔离:通过不同的 StpLogic 实例或内存存储实例隔离
- 数据易失:应用重启后所有会话丢失
3.4.2 全局基础配置 config/sa_token.php
1 |
|
3.4.3 公共服务提供者(内存模式)
1 |
|
3.4.4 内存模式下的多应用隔离
1 | // ========== 方式一:通过不同的 StpLogic 实例隔离 ========== |
3.4.5 四种模式完整对比总结
| 对比项 | 单应用+Redis | 单应用+内存 | 多应用+Redis | 多应用+内存 |
|---|---|---|---|---|
| Redis 依赖 | ✅ 需要 | ❌ 不需要 | ✅ 需要 | ❌ 不需要 |
| 数据持久化 | ✅ | ❌ | ✅ | ❌ |
| 分布式支持 | ✅ | ❌ | ✅ | ❌ |
| 多应用支持 | ❌ | ❌ | ✅ | ✅ |
| 应用间共享会话 | N/A | N/A | ✅ | ❌ |
| 部署复杂度 | 中 | 低 | 中 | 中 |
| 性能 | 高 | 极高 | 高 | 极高 |
| 推荐环境 | 生产 | 开发/测试 | 生产/微服务 | 开发/小型项目 |
| 数据存储位置 | Redis | 进程内存 | Redis | 进程内存 |
| 集群扩展性 | 优秀 | 不可用 | 优秀 | 不可用 |
四、登录认证系统
4.1 创建认证控制器
1 |
|
4.2 登录参数详解
1 | use SaToken\SaLoginParameter; |
4.3 获取当前登录信息
1 | // ========== 基础信息 ========== |
4.4 Token 操作
1 | // ========== Token 刷新 ========== |
4.5 踢人下线
1 | // ========== 踢人操作 ========== |
4.6 账号封禁
1 | // ========== 封禁操作 ========== |
4.7 多账号体系
1 | use SaToken\StpLogic; |
4.8 身份切换
1 | // ========== 切换到指定用户 ========== |
五、权限认证系统
5.1 权限校验方法
1 | use SaToken\StpUtil; |
5.2 角色校验
1 | // ========== 校验(不通过抛异常 NotRoleException) ========== |
5.3 二级认证
1 | // ========== 二级认证概述 ========== |
5.4 权限数据注入
1 | // ========== 在服务提供者中注入权限获取逻辑 ========== |
六、Cookie 与 Session 管理
6.1 Cookie 管理详解
Sa-Token 中的 Cookie 管理是认证流程的核心环节。Token 通过 Cookie 在客户端和服务端之间传递。
6.1.1 Cookie 配置项详解
1 | // config/sa_token.php |
6.1.2 Cookie 各配置项详细说明
| 配置项 | 类型 | 默认值 | 详细说明 |
|---|---|---|---|
cookieName |
string | satoken |
Cookie 的名称,用于存储 Token。建议与 tokenName 保持一致。多应用环境下可不同。 |
cookieDomain |
string | '' |
Cookie 的作用域。空字符串表示当前域名。设置如 .example.com 可在子域名间共享。 |
cookiePath |
string | '/' |
Cookie 的路径。'/' 表示整个网站都有效。可设置为 /admin 限制仅后台使用。 |
cookieSecure |
bool | false |
是否仅通过 HTTPS 传输。生产环境建议 true。 |
cookieHttpOnly |
bool | true |
是否禁止 JavaScript 读取 Cookie。建议 true 防止 XSS 攻击。 |
cookieSameSite |
string | 'Strict' |
CSRF 防护策略。Strict 最安全,Lax 兼容性更好,None 需要配合 Secure。 |
cookieMaxAge |
int | 86400 |
Cookie 在客户端的最大存活时间(秒)。与 Token timeout 配合使用。 |
cookiePrefix |
string | '' |
Cookie 前缀。可设置如 __Secure- 增强安全性。 |
6.1.3 Cookie 读写操作
1 | // ========== Sa-Token 自动 Cookie 操作 ========== |
6.1.4 Cookie 常见场景配置
1 | // ========== 场景1:前后端分离(API 模式) ========== |
6.1.5 Cookie 前缀说明
1 | // 使用 Cookie 前缀可以增强安全性 |
6.1.6 跨域 Cookie 配置
1 | // ========== 后端配置 ========== |
6.2 Session 管理详解
Sa-Token 的 Session 机制用于在用户登录期间存储状态数据。
6.2.1 Session 类型
Sa-Token 提供三种 Session:
| Session 类型 | 作用范围 | 说明 |
|---|---|---|
| 账号 Session | 当前账号的所有 Token | 登录后,同一账号的所有设备共享此 Session |
| Token Session | 当前 Token | 只对当前 Token 有效,不同设备相互隔离 |
| 自定义 Session | 自定义 Key | 开发者任意指定的 Session 对象 |
1 | // ========== 账号 Session(所有设备共享) ========== |
6.2.2 Session 操作详解
1 | // ========== Session 存储 ========== |
6.2.3 Session 配置
1 | // config/sa_token.php |
6.2.4 Session 清理机制
1 | // ========== 自动清理 ========== |
6.2.5 Session 存储引擎对比
| 存储引擎 | 持久化 | 分布式 | 性能 | 适用场景 |
|---|---|---|---|---|
| 内存(Memory) | ❌ | ❌ | 极高 | 开发测试 |
| Redis | ✅ | ✅ | 高 | 生产环境 |
| PSR-16(Cache) | ✅ | ✅ | 中 | 通用适配 |
6.2.6 Session 实战示例 - 购物车
1 |
|
6.3 Cookie 与 Session 交互完整流程图
1 | ┌─────────────────────────────────────────────────────────────────────────────┐ |
七、注解式鉴权
7.1 注解概览
Sa-Token 提供 9 个注解,用于优雅地将鉴权与业务代码分离:
| 注解 | 说明 | 示例 |
|---|---|---|
@SaCheckLogin |
登录校验 | #[SaCheckLogin] |
@SaCheckRole |
角色校验 | #[SaCheckRole('admin')] |
@SaCheckPermission |
权限校验 | #[SaCheckPermission('user:add')] |
@SaCheckSafe |
二级认证校验 | #[SaCheckSafe] |
@SaCheckHttpBasic |
HttpBasic 认证 | #[SaCheckHttpBasic] |
@SaCheckHttpDigest |
HttpDigest 认证 | #[SaCheckHttpDigest] |
@SaCheckDisable |
服务封禁校验 | #[SaCheckDisable('comment')] |
@SaCheckSign |
API 签名校验 | #[SaCheckSign] |
@SaIgnore |
忽略校验 | #[SaIgnore] |
7.2 基本用法
1 |
|
7.3 多权限场景:AND 和 OR 模式
1 | use SaToken\Annotation\SaCheckPermission; |
7.4 角色和权限混着校验
1 | /** |
7.5 复杂组合校验
1 | use SaToken\Annotation\SaCheckOr; |
八、路由拦截鉴权
8.1 基础匹配
1 | use SaToken\SaRouter; |
8.2 排除路径
1 | // 排除指定路径 |
8.3 复杂鉴权
1 | // 组合校验 |
8.4 链式匹配
1 | // 多个规则链式匹配 |
8.5 在中间件中使用 SaRouter
1 | // app/middleware/SaTokenMiddleware.php |
九、SSO 单点登录
9.1 SSO 配置 config/sa_token_sso.php
1 |
|
9.2 SSO 控制器
1 |
|
十、OAuth2.0 认证
10.1 OAuth2 配置 config/sa_token_oauth2.php
1 |
|
10.2 OAuth2 控制器
1 |
|
十一、安全防护体系
11.1 防暴力破解
1 | /** |
11.2 Token 黑名单
1 | // ========== Token 黑名单操作 ========== |
11.3 IP 异常检测
1 | use SaToken\StpUtil; |
11.4 设备管理
1 | use SaToken\StpUtil; |
11.5 敏感操作验证
1 | use SaToken\StpUtil; |
11.6 Token 指纹绑定
1 | // ========== 启用 Token 指纹绑定 ========== |
十二、高级功能
12.1 HTTP Basic/Digest 认证
1 | use SaToken\SaToken; |
12.2 参数签名校验(SaSign)
1 | use SaToken\SaToken; |
12.3 API Key 秘钥授权
1 | use SaToken\SaToken; |
12.4 全局过滤器
1 | use SaToken\SaToken; |
12.5 自定义存储
1 | use SaToken\SaToken; |
12.6 JWT 集成
1 | use SaToken\Plugin\SaTokenJwt; |
12.7 密码加密工具
1 | use SaToken\Plugin\SaTokenCrypto; |
12.8 审计日志
1 | use SaToken\StpUtil; |
12.9 事件监听(全局侦听器)
1 | use SaToken\Listener\SaTokenListenerInterface; |
十三、异常处理体系
13.1 异常类列表
| 异常类 | 触发场景 | 关联方法 |
|---|---|---|
NotLoginException |
未登录/Token 无效/过期/被踢 | StpUtil::checkLogin() |
NotPermissionException |
权限校验不通过 | StpUtil::checkPermission() |
NotRoleException |
角色校验不通过 | StpUtil::checkRole() |
DisableServiceException |
账号被封禁 | StpUtil::checkLogin() |
NotSafeException |
二级认证校验不通过 | StpUtil::checkSafe() |
SaTokenException |
其他异常 | 所有方法 |
13.2 异常类型详解
1 | use SaToken\Exception\NotLoginException; |
13.3 异常处理器
1 |
|
十四、完整配置参考
14.1 完整配置项
1 |
|
十五、项目结构与部署指南
15.1 单应用项目结构
1 | tp8-sa-token/ |
15.2 多应用项目结构
1 | tp8-sa-token/ |
15.3 四种模式部署检查清单
| 检查项 | 单应用+Redis | 单应用+内存 | 多应用+Redis | 多应用+内存 |
|---|---|---|---|---|
配置文件 config/sa_token.php |
✅ | ✅ | ✅ | ✅ |
| Redis 服务运行 | ✅ | ❌ | ✅ | ❌ |
| Redis 扩展安装 | ✅ | ❌ | ✅ | ❌ |
| 服务提供者注册 | ✅ | ✅ | ✅ | ✅ |
| 权限服务实现 | ✅ | ✅ | ✅ | ✅ |
| 中间件注册 | ✅ | ✅ | ✅ | ✅ |
| 路由配置 | ✅ | ✅ | ✅ | ✅ |
| 异常处理器 | ✅ | ✅ | ✅ | ✅ |
| 多应用扩展 | ❌ | ❌ | ✅ | ✅ |
| 数据库迁移 | ✅ | ✅ | ✅ | ✅ |
十六、API 快速参考手册
16.1 StpUtil 核心方法
| 方法 | 说明 |
|---|---|
login($loginId, $extra) |
登录 |
logout() |
登出 |
isLogin() |
判断是否登录 |
getLoginId() |
获取登录 ID |
getTokenValue() |
获取 Token |
getTokenTimeout() |
获取 Token 剩余有效期 |
refreshToken() |
刷新 Token |
kickout($loginId) |
踢人下线 |
disable($loginId, $time) |
封禁账号 |
untieDisable($loginId) |
解封账号 |
checkPermission($perm) |
校验权限 |
checkRole($role) |
校验角色 |
getPermissionList() |
获取权限列表 |
getRoleList() |
获取角色列表 |
switchTo($loginId) |
身份切换 |
switchBack() |
切回原身份 |
setSession($key, $value) |
设置 Session |
getSession($key) |
获取 Session |
getExtra($key) |
获取扩展信息 |
updateExtra($key, $value) |
更新扩展信息 |
getTokenInfo() |
获取 Token 完整信息 |
getLoginDevice() |
获取登录设备 |
getLoginType() |
获取登录类型 |
checkToken($token) |
检查 Token 有效性 |
getLoginIdByToken($token) |
通过 Token 获取 LoginId |
replaceToken() |
替换 Token |
addTokenToBlacklist($token) |
加入黑名单 |
removeTokenFromBlacklist($token) |
移除黑名单 |
isTokenBlacklisted($token) |
判断是否在黑名单 |
disableService($loginId, $service) |
封禁服务 |
untieDisableService($loginId, $service) |
解封服务 |
isDisableService($loginId, $service) |
判断服务是否被封禁 |
getDisableServiceTime($loginId, $service) |
获取服务封禁剩余时间 |
openSafe() |
开启二级认证 |
checkSafe() |
校验二级认证 |
isSafe() |
判断二级认证状态 |
closeSafe() |
关闭二级认证 |
getSafeTimeout() |
获取二级认证剩余时间 |
16.2 Session 操作方法
| 方法 | 说明 |
|---|---|
setSession($key, $value) |
设置 Session |
getSession($key, $default) |
获取 Session |
hasSession($key) |
判断 Session 是否存在 |
deleteSession($key) |
删除 Session |
clearSession() |
清空所有 Session |
getSessionKeys() |
获取所有 Session Key |
setTokenSession($key, $value) |
设置 Token Session |
getTokenSession($key) |
获取 Token Session |
deleteTokenSession($key) |
删除 Token Session |
setSessionTimeout($key, $timeout) |
设置 Session 有效期 |
getSessionTimeout($key) |
获取 Session 剩余时间 |
refreshSession($key) |
刷新 Session 有效期 |
clearUserSession($loginId) |
清理用户 Session |
16.3 安全防护方法
| 方法 | 说明 |
|---|---|
checkAntiBrute($key) |
检查防暴力破解 |
recordAntiBruteFailure($key) |
记录失败次数 |
clearAntiBruteFailure($key) |
清除失败记录 |
getAntiBruteInfo($key) |
获取防暴力破解信息 |
isAccountLocked($key) |
判断账号是否锁定 |
getRemainingLockTime($key) |
获取剩余锁定时间 |
unlockAccount($key) |
解锁账号 |
getLoginInfo($loginId) |
获取登录信息 |
getAnomalyCount($loginId) |
获取异常次数 |
getIpHistory($loginId) |
获取 IP 历史 |
clearLoginHistory($loginId) |
清除登录历史 |
isIpAnomalous() |
判断 IP 是否异常 |
getDeviceList($loginId) |
获取设备列表 |
getDeviceCount($loginId) |
获取设备数量 |
kickoutDevice($loginId, $deviceId) |
踢出设备 |
kickoutAllDevices($loginId, $currentToken) |
踢出所有设备 |
generateOtpCode($service) |
生成 OTP 验证码 |
sendOtpCode($service) |
发送 OTP 验证码 |
verifyOtpCode($service, $code) |
验证 OTP 验证码 |
isSensitiveVerified($service) |
检查是否已验证 |
clearSensitiveVerify($service) |
清除验证状态 |
openSensitiveVerify($service, $timeout) |
开启安全令牌 |
checkSensitiveVerify($service, $token) |
校验安全令牌 |
16.4 SaRouter 核心方法
| 方法 | 说明 |
|---|---|
match($path, $method) |
匹配路由 |
exclude($path) |
排除路径 |
check($callback) |
执行校验 |
addBeforeFilter($callback) |
添加前置过滤器 |
addAfterFilter($callback) |
添加后置过滤器 |
16.5 异常类
| 异常类 | 说明 |
|---|---|
NotLoginException |
未登录异常 |
NotPermissionException |
无权限异常 |
NotRoleException |
无角色异常 |
DisableServiceException |
账号封禁异常 |
NotSafeException |
二级认证异常 |
SaTokenException |
基础异常 |
十七、常见问题与解决方案
17.1 配置与初始化问题
Q1: 为什么 Sa-Token 不生效?
A: 检查以下几点:
- 是否正确注册了服务提供者
app/provider/SaTokenProvider.php - 是否在
config/service.php中注册了服务提供者 - 是否正确加载了配置文件
config/sa_token.php - 是否注册了中间件
config/middleware.php - 是否在路由中正确使用了中间件
Q2: Token 没有自动写入 Cookie?
A: 检查配置:
1 | 'isWriteCookie' => true, // 必须为 true |
Q3: 如何在多应用中使用不同的配置?
A: 使用多应用+Redis/内存模式,各应用在 app/{app}/config/sa_token.php 中配置差异化参数。配置会与全局配置合并。
Q4: 注解鉴权为什么不生效?
A: 注解鉴权需要确保:
- 正确使用了注解标签
- 注解类已正确导入
- 中间件已正确注册
- PHP 版本支持注解(PHP 8+)
17.2 Cookie 与 Session 问题
Q5: Cookie 和 Session 的数据存储在哪里?
A: Cookie 存储在客户端浏览器中,Session 存储在服务端(Redis 或内存)。具体位置由 storage 配置决定。
Q6: Session 数据会丢失吗?
A: 内存模式下应用重启会丢失,Redis 模式下不会丢失。生产环境强烈推荐使用 Redis 模式。
Q7: 如何跨域共享 Cookie?
A:
- 配置
cookieDomain = '.example.com' - 配置
cookieSameSite = 'Lax'或'None' - 如使用
None,必须设置cookieSecure = true - 前端请求需配置
credentials: 'include'
Q8: 前后端分离如何使用 Session?
A: 建议关闭 Cookie,使用 Header 传递 Token:
1 | 'isReadCookie' => false, |
17.3 Token 相关
Q9: Token 过期了怎么办?
A:
- 启用 RefreshToken:
refreshToken => true - 客户端调用刷新接口获取新 Token
- 或重新登录
Q10: 如何实现 Token 自动续签?
A: 配置 activityTimeout > 0,每次请求自动刷新 Token 有效期。
Q11: 如何实现同端互斥登录?
A: 设置 concurrent => false,同一账号在同一设备类型只能登录一个。
Q12: Token 风格有哪些?
A: 支持以下风格:
uuid: UUID 格式 (550e8400-e29b-41d4-a716-446655440000)simple-uuid: 简化 UUID (550e8400e29b41d4a716446655440000)random-32: 32位随机字符串random-64: 64位随机字符串random-128: 128位随机字符串tik: 24位随机字符串
17.4 性能与安全
Q13: 生产环境推荐哪种模式?
A: 强烈推荐 单应用+Redis 或 多应用+Redis,支持数据持久化和分布式部署。
Q14: 如何防止暴力破解?
A: 启用防暴力破解:
1 | 'antiBruteMaxFailures' => 5, |
Q15: 如何防止 Token 盗用?
A:
- 启用 Token 指纹绑定:
tokenFingerprint => true - 使用 HTTPS + Secure Cookie
- 设置合理的 Token 有效期
- 敏感操作使用二级认证
Q16: 性能优化建议?
A:
- 使用 Redis 存储替代内存存储
- 权限数据使用 Session 缓存
- 合理设置
activityTimeout - 生产环境关闭调试日志
- 使用独立 Redis 实例存储认证数据
17.5 多应用
Q17: 多应用如何共享用户信息?
A: 使用多应用+Redis 模式,各应用共享 Redis 存储。Token 在应用间自动共享。
Q18: 多应用如何隔离数据?
A: 使用不同的 Redis key 前缀:
1 | 'redis' => ['prefix' => 'sa_token_api_'], |
各应用数据通过前缀隔离,但 Token 验证逻辑共享。
Q19: 多应用如何实现各自独立的权限体系?
A: 在 app/{app}/service/ 中创建各自的权限服务类,在服务提供者中根据应用名注入不同的服务。
Q20: 内存模式可以跨应用共享会话吗?
A: 不可以。内存模式各应用数据独立,无法共享。多应用内存模式仅适合开发测试。
项目地址: https://github.com/pohoc/sa-token
ThinkPHP 8 文档: https://www.thinkphp.cn/doc
Sa-Token 官方文档: https://sa-token.cc
问题反馈: GitHub Issues

