sanctum鉴权中间件严格按场景区分:spa前端必须用auth:sanctum+cookie/csrf,纯api必须用auth:sanctum+bearer token;中间件名不可简写,配置错误将导致401或419。

直接说结论:Sanctum 的鉴权中间件不是“选一个用”,而是按场景严格区分——SPA 前端必须用 auth:sanctum + Cookie/CSRF 流程,纯 API(如移动端、Postman)也必须用 auth:sanctum + Bearer Token,不能换成 sanctum 或 auth 等简写。 文档里若写错中间件名、混用场景或漏掉前置配置,前端永远 401 或 419。
中间件名称和用途必须一一对应
Sanctum 提供的中间件有明确分工,不能凭字面猜测:
-
auth:sanctum是唯一用于路由保护的守卫中间件,必须完整书写;写成sanctum、auth或api:sanctum都会失败,Laravel 找不到对应 guard -
EnsureFrontendRequestsAreStateful是内部中间件,自动判断是否走 session 分支,不能手动加到路由上,只应在$middlewareGroups['web']或['api']中按位置启用 -
CheckAbilities用于权限能力校验(如['read', 'edit']),需配合createToken('name', ['read'])使用,单独用不生效
API 路由必须用 auth:sanctum,且不能省略 Bearer 头
纯接口调用(比如 Postman、Flutter App、curl)默认不带 cookie,auth:sanctum 会直接 fallback 到数据库查 token:
- 请求头必须为
Authorization: Bearer eyJ0eXAiOi...,注意 Bearer 后有一个空格,少则 401 - token 必须来自已登录用户的
$user->createToken('mobile')->plainTextToken,不能在 tinker 里硬插数据库 - 数据库中
personal_access_tokens表的tokenable_type字段长度建议设为 255(默认 191 不够全类名)
SPA 前端要过 CSRF,不是“加个中间件”就完事
Vue/React 前端跑在 http://localhost:5173,和 Laravel 后端不同域,必须满足三要素才能走 session 分支:
- 后端
config/cors.php中'supports_credentials' => true,且'allowed_origins'写具体域名(不能是*) - 前端发请求前,先 GET
/sanctum/csrf-cookie(该路由不能加任何中间件) - axios 要设
withCredentials: true,fetch 要加credentials: 'include'
多模型支持需改底层逻辑,不能只换 trait
想让 Admin 和 User 共用 Sanctum token 表但隔离认证,光在 Admin 模型加 HasApiTokens 不行:
- 必须在
config/auth.php新增guards.admin,driver 设为sanctum,provider 指向admins - 重写
Sanctum::$personalAccessTokenModel(Laravel 9.2+)或继承PersonalAccessToken类,覆盖tokenableType()返回App\Models\Admin::class - 迁移中调整
tokenable_type字段长度,并确保admins表主键类型与tokenable_id匹配(如都是 bigint)











