Laravel怎么实现API身份验证 _ Laravel Sanctum令牌配置方法【教程】

1次阅读

sanctum 令牌通过 $user->createtoken(‘login’)->plaintextToken 生成并返回明文 token 给前端;须配置 sanctum_stateful_domains、正确注册中间件、按场景选择 cookie 或 bearer 方式安全传递,并主动调用 revoke 管理生命周期。

Laravel怎么实现API身份验证 _ Laravel Sanctum令牌配置方法【教程】

Sanctum 令牌怎么生成并返回给前端

生成令牌不是靠手动写 sql 或硬编码,而是调用 createToken() 方法。它会自动创建加密 token、存进数据库personal_access_tokens 表),并返回一个带明文令牌的 AccessToken 实例——这个明文值必须在登录成功后立刻发给前端,之后就再也看不到了。

常见错误是生成后没取 plainTextToken,而是直接返回整个模型,导致前端拿到的是空字符串或报错 Object of class laravelSanctumNewAccessToken could not be converted to String

  • 登录成功后必须用 $user->createToken('login')->plainTextToken 取值
  • 不要用 $user->tokens()->create(...) 手动建,会绕过 Sanctum 的哈希和作用域逻辑
  • 如果用了 tokenable_type 自定义模型(比如不是 User),要确保 HasApiTokens trait 已正确引入

Laravel 10+ 中 Sanctum 中间件为啥不生效

最常踩的坑是中间件注册顺序不对,或者用了错误的中间件别名。Sanctum 默认依赖 EnsureFrontendRequestsAreStateful 来判断是否走 session 认证,而它只对匹配 localhost127.0.0.1 或你配置的 SANCTUM_STATEFUL_DOMAINS 的请求放行。如果你前端跑在 http://test.local:3000,但没加进环境变量,就会静默 fallback 到 token 认证,而你又没传 Authorization: Bearer xxx,结果就是 401。

  • 检查 .env 是否设置了 SANCTUM_STATEFUL_DOMAINS=test.local(多个用逗号分隔,不要带协议或端口)
  • api 路由组必须用 middleware(['auth:sanctum']),不能只写 auth
  • 确认 app/Http/Kernel.phpapi 中间件组里包含 throttle:apiauth:sanctum,且顺序无误

前端怎么安全存和传 Sanctum token

token 是长期有效的(除非手动 revoke),所以不能存在 localStorage——xss 一触发就全丢。推荐存在 httpOnly cookie 是 Sanctum 默认方案,但前提是前后端同域或已配好跨域信任;如果必须跨域(比如 Vue 前端在 port 3000,Laravel 在 port 8000),就得改用 Bearer header 方式,此时 token 必须由前端 js 管理,那就只能退而求其次存在内存变量 + 登出清空,避免写入持久化存储。

  • 使用 cookie 方式时,确保响应头有 Set-Cookie: laravel_session=xxx; expires=...; path=/; secure; httponly; samesite=lax
  • 用 Bearer 方式时,每次请求必须手动加 Authorization: Bearer <code>tokenaxios 可通过 defaults.headers.common['Authorization'] 设置
  • 不要把 token 拼在 URL 里传,容易被日志、代理、Referer 泄露

revokeToken() 不起作用?查这三处

调用 $user->currentAccessToken()->delete()$user->tokens()->delete() 后仍能访问,大概率是缓存或 token 解析没走数据库。Sanctum 默认用 DatabaseTokenProvider,但如果你在 config/sanctum.php 里改过 guardprovider,或自定义了 PersonalAccessToken 模型但没重写 findToken(),就会跳过实际校验。

  • 确认 config/sanctum.phpstateful 域名列表和当前请求 Host 完全匹配(大小写、有无 www 都算不同)
  • 检查 PersonalAccessToken 模型是否仍继承 HasAbilitiesHasFactory,否则 can()delete() 可能静默失败
  • 执行 php artisan config:clearphp artisan cache:clear,避免旧配置残留

token 的生命周期管理不像 Passport 那样自带 TTL,它完全依赖你主动 delete,这点很容易被忽略——用户登出、密码修改、设备解绑这些场景都得显式调用 revoke,不能指望“过期自动失效”。

text=ZqhQzanResources