Sanctum的abilities权限不通过请求头识别,而是存于数据库personal_access_tokens表中,由auth:sanctum中间件在Bearer Token认证时查表比对;Cookie认证路径下abilities完全不生效。

Sanctum 的 token abilities(权限能力)不是靠请求头自动识别的,而是存在数据库里、在每次请求时由中间件查表比对。认证失败却以为是 token 无效?大概率是 abilities 不匹配、或根本没传对 token 类型——先确认你用的是 cookie 认证还是 token 认证,再查 abilities 是否被正确写入和校验。
确认当前请求走的是哪种认证方式
Sanctum 默认同时支持两种模式:前端 Cookie 会话(stateful)和 API Token(token-based)。它们互不干扰,但验证逻辑完全不同:
- 如果前端访问域名在 SANCTUM_STATEFUL_DOMAINS 白名单中(如
sub.my-domain.com),且已成功调用/sanctum/csrf-cookie,那后续请求走的是 session + XSRF-TOKEN Cookie 认证,完全不看 Authorization: Bearer 头 - 如果你手动在 Postman 或移动端加了
Authorization: Bearer xxx,那走的是 personal_access_tokens 表查询,此时才真正依赖abilities字段 -
X-Sanctum-Token请求头原生不被 Sanctum 识别——它是 Jetstream 或某些 SDK 封装的别名,后端不会读它
查看 token 的 abilities 是否写入正确
登录时生成 token 必须显式传 abilities 数组,否则默认为空(即只能访问无权限要求的接口):
- 生成示例:
$token = $user->createToken('login', ['read:posts', 'write:comments']); - 检查数据库:
personal_access_tokens表中对应记录的 abilities 字段应为 JSON 数组字符串,如["read:posts","write:comments"],不是逗号分隔或空格分隔 - 若字段值为
null或[],则$user->tokenCan('read:posts')永远返回 false
调试 abilities 校验是否生效
不要只看响应状态码,要进代码里验证中间件是否真走到能力判断这一步:
- 在受保护路由中临时加一行:
dd(request()->bearerToken(), Auth::user()?->currentAccessToken?->abilities);,确认 token 能解出、且 abilities 数组非空 - 用
$user->tokenCan('read:posts')手动测试——注意:这个方法只对当前已认证用户的 当前 token 有效,不是查所有 token - 若需校验特定 token(比如从 header 提取的),可用:
use Laravel\Sanctum\PersonalAccessToken; $token = PersonalAccessToken::findToken($plainText); dd($token?->can('read:posts'));
常见 abilities 相关错误操作
这些写法看似合理,实则导致 abilities 失效:
- 调用
$user->createToken('login')->plainTextToken但没传第二个参数 → abilities 为空数组 - 用
$user->tokens()->create([...])手动插入记录 → 绕过 Sanctum 的哈希与 abilities 序列化逻辑,abilities 字段可能存成字符串或格式错误 - 在中间件里写
auth:sanctum['read:posts']—— Sanctum 不支持这种语法,权限必须在控制器或策略里用$user->tokenCan()显式判断 - 数据库字段
abilities类型不是TEXT或JSON(Laravel 9+ 推荐 JSON 类型),旧迁移可能用 VARCHAR(255),存长权限列表会被截断
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











