sanctum token 必须登录后通过已认证用户调用 createtoken() 获取明文 token,且 plaintexttoken 仅首次有效;请求头需严格为“bearer + 空格 + token”;本地跨域需配置 session_driver=cookie、sanctum_stateful_domains 及 credentials: 'include'。

Sanctum token 生成前必须先登录用户
Sanctum 不提供独立的「生成 token」函数,它只在用户成功认证后自动发放 token。你不能跳过登录流程,直接调用 createToken() 就拿到可用 API token——那只是个未绑定 session 或 device 的裸 token,后续请求会被拒绝。
- 必须通过
Auth::attempt()或已登录的$user实例调用createToken() - 推荐在登录接口里做:验证账号密码 → 获取
$user→ 调用$user->createToken('api')->plainTextToken - 别在迁移或 tinker 里硬造 token,它没关联 CSRF、session 或 device 指纹,Sanctum 中间件会直接 401
createToken() 返回的 plainTextToken 只能读一次
这是最容易丢 token 的地方。调用 $user->createToken('api') 返回的是一个 PersonalAccessToken 实例,plainTextToken 是它的临时属性,只在创建当次有效。下次再查这个 token 对象,plainTextToken 就是 null。
- 必须在创建后立刻保存或返回:
$token = $user->createToken('api'); return response(['token' => $token->plainTextToken]); - 不能先存对象、再取字段:
$token->plainTextToken在 response 之外访问大概率为空 - 数据库里存的是哈希后的
token字段(不可逆),前端需要的明文 token 只有plainTextToken这一次机会
前端请求头必须带 Bearer + 空格 + token
Sanctum 中间件对 Authorization 头极其严格。常见 401 不是因为 token 错,而是格式不对。
- 正确写法:
Authorization: Bearer <font color="red"> </font>abc123...(注意 Bearer 后必须有一个空格) - 错例:
Bearerabc123、Bearer: abc123、token abc123—— 全部 401 - 如果用 Axios,别手拼 header:
headers: { 'Authorization': `Bearer ${token}` },确保模板字符串里空格存在 - Vue/React 开发时,检查浏览器 Network 面板里的 Request Headers,确认值是
Bearer xxx而非其他变体
本地开发跨域需配好 SANCTUM_STATEFUL_DOMAINS 和 SESSION_DRIVER
很多人本地 Vue 前端跑在 http://localhost:5173,Laravel API 在 http://localhost:8000,结果登录成功但后续请求始终 401——问题不在 token,而在 session 无法共享。
-
.env必须设:SESSION_DRIVER=cookie(不能是 database 或 redis) -
SANCTUM_STATEFUL_DOMAINS=localhost:5173(多个用逗号,不加协议,端口必须写) - 前端 fetch/Axios 要开
credentials: 'include',否则 cookie 不发送 - Chrome 120+ 对 localhost 跨端口默认禁用第三方 cookie,若仍失败,可临时改用
127.0.0.1:5173绕过
Sanctum 的 token 本质是「带签名的 session ID」,不是 JWT。它依赖底层 session 机制存活,所有问题几乎都卡在「登录了但没建立可信 session 管道」这一步。绕开这个前提去调试 token 字符串本身,基本白忙。









