sanctum 本身不慢,性能瓶颈源于配置错误:auth:sanctum 强制启动 session、personal_access_tokens 表未加唯一索引、token 查询未缓存、api 路由混用 startsession 中间件、token 泄露未回收及冗余 eager load。

Sanctum 本身不支持「提速」式优化——它的验证逻辑本就极轻量,瓶颈从来不在 Sanctum 自身,而在你配错中间件、漏掉缓存、或误用 token 模式。
auth:sanctum 中间件为什么慢?
常见现象是 API 响应延迟明显,尤其在高并发下。根本原因不是 Sanctum 验证慢,而是它默认走完整 Laravel 认证流程:先查 session(如果请求带 Cookie),再 fallback 到数据库查 personal_access_tokens 表。但如果你的路由本就不该走 session(比如纯 API 调用),却仍被 auth:sanctum 强制触发 session 启动,就会多一次不必要的 session 存储读取(如 Redis 或 file)。
- 只用于 API 的路由,改用
auth:sanctum:api(需自定义中间件别名)或直接用auth:api+ Sanctum 的 token 解析逻辑 - 确保
stateful域名配置中不含你的 API 前端域名(如api.example.com不该出现在SANCTUM_STATEFUL_DOMAINS) - 检查
App\Http\Kernel.php中web和api中间件组是否混用了StartSession—— API 组必须剔除它
personal_access_tokens 表查询能缓存吗?
能,但 Sanctum 默认不缓存。每次请求带 Authorization: Bearer xxx,它都会执行一次 DB 查询(tokenable_id + tokenable_type + token 哈希比对)。这个查询无法靠 Eloquent ORM 自动缓存,因为 token 字段是加密哈希值,且查询条件不走主键。
- 手动加缓存:在
AuthServiceProvider::boot()中重写 Sanctum 的 token 查找逻辑,用Cache::remember()包裹PersonalAccessToken::findToken($plainToken)的结果(注意 key 要含哈希前缀,避免碰撞) - 更稳妥的做法是:把
token字段设为唯一索引(它本来就是),并确认 MySQL/PostgreSQL 已启用 query cache 或使用连接池减少握手开销 - 不要缓存整个
User模型——token 验证阶段只需确认存在性与作用域,$user->with('tokens')->find($id)这类 eager load 是典型冗余
createToken() 后反复查数据库?
不是 Sanctum 的问题,是你没管好 token 生命周期。调用 $user->createToken('name') 会立刻写库;后续每次请求验证,都得查这条记录。如果你允许用户无限创建 token(比如每登录一次就生成一个新 token 而不 revoke 旧的),表会膨胀,索引效率下降。
- 登录时先
$user->currentAccessToken()->delete()清掉当前设备旧 token(前提是已登录) - 限制每个用户最多存 5 个 active token:
$user->tokens()->count() >= 5 && $user->tokens()->oldest()->first()->delete() - 避免在
createToken()第二个参数传空数组[]—— 这会导致abilities字段存null,而 Sanctum 的tokenCan()在判空时会额外走一次 JSON 解析
真正卡顿的地方,往往藏在你以为「Sanctum 干了什么」的误解里:它不加密 payload、不验签名、不刷新过期时间——所有「重」操作都是你加的中间件、ORM 关系或日志钩子干的。盯住 laravel.log 里的 slow query 日志,比调优 Sanctum 本身有用十倍。











