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 是一个轻量级权限认证框架,专为 PHP 8.1+ 设计,完美适配 ThinkPHP 8.0+。登录认证只需一行代码:
1 | StpUtil::login(10001); |
权限校验也只需一行:
1 | StpUtil::checkPermission('user:add'); |
1.2 核心功能矩阵
| 类别 | 功能 | 说明 |
|---|---|---|
| 登录认证 | 单端登录 | 一个账号只能在一个设备登录 |
| 多端登录 | 一个账号可在多个设备同时登录 | |
| 同端互斥登录 | 同一设备类型只能登录一个 | |
| 记住我 | 延长登录有效期 | |
| 踢人下线 | 强制指定用户下线 | |
| 账号封禁 | 禁止账号登录指定时长 | |
| 服务封禁 | 封禁特定服务如评论、发帖 | |
| 权限认证 | 权限校验 | 判断用户是否拥有某权限 |
| 角色校验 | 判断用户是否拥有某角色 | |
| 二级认证 | 敏感操作二次身份验证 | |
| 身份切换 | 临时切换到其他用户身份 | |
| 注解式鉴权 | 通过注解声明鉴权规则 | |
| 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.3 核心术语
| 术语 | 说明 |
|---|---|
StpUtil |
静态工具类,提供所有认证 API |
StpLogic |
逻辑类,支持多账号体系隔离 |
SaRouter |
路由匹配器,用于 URL 拦截鉴权 |
Token |
身份凭证,由框架生成和管理 |
LoginId |
登录标识,通常为用户 ID |
SaTokenDao |
数据持久层接口,负责所有会话数据的底层写入和读取 |
Session |
会话对象,存储当前用户的状态数据 |
Cookie |
客户端存储 Token 的机制 |
二、环境要求与安装
2.1 环境要求
1 | PHP >= 8.1 |
2.2 创建项目
1 | # 创建单应用项目 |
2.3 安装 Sa-Token
1 | composer require pohoc/sa-token |
2.4 安装 Redis 扩展(Redis 模式必需)
1 | composer require predis/predis |
2.5 文件清单(使用前需创建)
| 序号 | 文件路径 | 说明 | 优先级 |
|---|---|---|---|
| 1 | config/sa_token.php |
主配置文件 | ✅ 必须 |
| 2 | config/sa_token_sso.php |
SSO 配置 | ⚠️ 按需 |
| 3 | config/sa_token_oauth2.php |
OAuth2.0 配置 | ⚠️ 按需 |
| 4 | app/service/PermissionService.php |
权限数据提供者 | ✅ 必须 |
| 5 | app/middleware/SaTokenMiddleware.php |
鉴权中间件 | ✅ 推荐 |
| 6 | app/exception/Handler.php |
异常处理器 | ✅ 推荐 |
| 7 | app/provider/SaTokenProvider.php |
服务提供者 | ✅ 推荐 |
| 8 | config/middleware.php |
中间件注册配置 | ✅ 必须 |
| 9 | config/service.php |
服务提供者注册 | ✅ 必须 |
| 10 | route/app.php |
路由配置 | ✅ 必须 |
三、四种部署模式详解
3.1 单应用 + Redis 模式
3.1.1 场景说明
适用于生产环境的单体应用,使用 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。
3.2.2 配置文件 config/sa_token.php
1 |
|
3.2.3 服务提供者 app/provider/SaTokenProvider.php(内存模式)
1 |
|
3.2.4 内存模式注意事项
1 | // ========== 内存模式特点 ========== |
其余文件(app/service/PermissionService.php、app/middleware/SaTokenMiddleware.php、config/service.php、config/middleware.php、route/app.php)与 3.1 节相同。
3.3 多应用 + Redis 模式
3.3.1 场景说明
适用于微服务架构或模块化中大型项目,多个应用共享 Redis 存储。
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 注册服务提供者 app/provider.php
1 |
|
3.3.10 API 应用路由 app/api/route/app.php
1 |
|
3.3.11 Admin 应用路由 app/admin/route/app.php
1 |
|
3.3.12 API 权限服务 app/api/service/ApiPermissionService.php
1 |
|
3.3.13 Admin 权限服务 app/admin/service/AdminPermissionService.php
1 |
|
3.4 多应用 + 内存模式
3.4.1 全局配置 config/sa_token.php
1 |
|
3.4.2 公共服务提供者 app/common/provider/SaTokenProvider.php(内存模式)
1 |
|
3.5 四种模式完整对比
| 对比项 | 单应用+Redis | 单应用+内存 | 多应用+Redis | 多应用+内存 |
|---|---|---|---|---|
| Redis 依赖 | ✅ 需要 | ❌ 不需要 | ✅ 需要 | ❌ 不需要 |
| 数据持久化 | ✅ | ❌ | ✅ | ❌ |
| 分布式支持 | ✅ | ❌ | ✅ | ❌ |
| 多应用支持 | ❌ | ❌ | ✅ | ✅ |
| 应用间共享会话 | N/A | N/A | ✅ | ❌ |
| 部署复杂度 | 中 | 低 | 中 | 中 |
| 性能 | 高 | 极高 | 高 | 极高 |
| 推荐环境 | 生产 | 开发/测试 | 生产/微服务 | 开发/小型项目 |
四、登录认证
4.1 创建认证控制器 app/controller/AuthController.php
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 管理详解
6.1.1 Cookie 配置项详解
1 | // config/sa_token.php |
6.1.2 Cookie 各配置项详细说明
| 配置项 | 类型 | 默认值 | 详细说明 |
|---|---|---|---|
cookieName |
string | satoken |
Cookie 的名称,用于存储 Token |
cookieDomain |
string | '' |
Cookie 的作用域,设置如 .example.com 可在子域名间共享 |
cookiePath |
string | '/' |
Cookie 的路径,'/' 表示整个网站都有效 |
cookieSecure |
bool | false |
是否仅通过 HTTPS 传输,生产环境建议 true |
cookieHttpOnly |
bool | true |
是否禁止 JavaScript 读取 Cookie,建议 true 防止 XSS |
cookieSameSite |
string | 'Strict' |
CSRF 防护策略:Strict/Lax/None |
cookieMaxAge |
int | 86400 |
Cookie 在客户端的最大存活时间(秒) |
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 管理详解
6.2.1 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.3 Cookie 与 Session 交互流程图
1 | ┌─────────────────────────────────────────────────────────────────────────────┐ |
七、注解式鉴权
7.1 注解概览
| 注解 | 说明 | 示例 |
|---|---|---|
@SaCheckLogin |
登录校验 | #[SaCheckLogin] |
@SaCheckRole |
角色校验 | #[SaCheckRole('admin')] |
@SaCheckPermission |
权限校验 | #[SaCheckPermission('user:add')] |
@SaCheckSafe |
二级认证 | #[SaCheckSafe] |
@SaCheckDisable |
服务封禁 | #[SaCheckDisable('comment')] |
@SaIgnore |
忽略校验 | #[SaIgnore] |
7.2 基本用法
1 |
|
7.3 多权限场景
1 | use SaToken\Annotation\SaCheckPermission; |
八、路由拦截鉴权
8.1 基础匹配
1 | use SaToken\SaRouter; |
8.2 排除路径
1 | SaRouter::match('/api/**') |
8.3 复杂鉴权
1 | SaRouter::match('/admin/**')->check(function() { |
8.4 链式匹配
1 | SaRouter::match('/api/**') |
九、SSO 单点登录
9.1 SSO 配置 config/sa_token_sso.php
1 |
|
9.2 SSO 控制器 app/controller/SsoController.php
1 |
|
十、OAuth2.0 认证
10.1 OAuth2 配置 config/sa_token_oauth2.php
1 |
|
10.2 OAuth2 控制器 app/controller/OAuth2Controller.php
1 |
|
十一、安全防护
11.1 防暴力破解
1 | public function login(): Json |
11.2 Token 黑名单
1 | StpUtil::addTokenToBlacklist($tokenValue); |
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 异常处理器 app/exception/Handler.php
1 |
|
十四、完整配置参考
1 |
|
十五、项目结构
15.1 单应用项目结构
1 | tp8-sa-token/ |
15.2 多应用项目结构
1 | tp8-sa-token/ |
十六、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) |
更新扩展信息 |
16.2 SaRouter 核心方法
| 方法 | 说明 |
|---|---|
match($path, $method) |
匹配路由 |
exclude($path) |
排除路径 |
check($callback) |
执行校验 |
16.3 异常类
| 异常类 | 说明 |
|---|---|
NotLoginException |
未登录异常 |
NotPermissionException |
无权限异常 |
NotRoleException |
无角色异常 |
DisableServiceException |
账号封禁异常 |
NotSafeException |
二级认证异常 |
SaTokenException |
基础异常 |
十七、常见问题
Q1: 四种模式如何选择?
| 场景 | 推荐模式 |
|---|---|
| 生产环境、高并发 | 单应用+Redis |
| 开发测试、快速验证 | 单应用+内存 |
| 微服务、分布式 | 多应用+Redis |
| 小型多模块项目 | 多应用+内存 |
Q2: 为什么 Sa-Token 不生效?
检查:
app/provider/SaTokenProvider.php是否正确注册config/service.php是否注册了服务提供者config/sa_token.php是否正确加载config/middleware.php是否注册了中间件
Q3: Token 没有自动写入 Cookie?
检查配置:
1 | 'isWriteCookie' => true, |
Q4: 如何跨域共享 Cookie?
1 | 'cookieDomain' => '.example.com', |
Q5: 前后端分离如何使用?
1 | 'isReadCookie' => false, |
Q6: 生产环境推荐哪种模式?
强烈推荐 单应用+Redis 或 多应用+Redis。
Q7: Session 数据会丢失吗?
内存模式下应用重启会丢失,Redis 模式下不会。
Q8: 如何实现 Token 自动续签?
配置 activityTimeout > 0,每次请求自动刷新 Token 有效期。
项目地址: https://github.com/pohoc/sa-token
ThinkPHP 8 文档: https://www.thinkphp.cn/doc
问题反馈: https://github.com/pohoc/sa-token/issues
评论
匿名评论隐私政策
✅ 你无需删除空行,直接评论以获取最佳展示效果

