laravel 401 unauthorized 根本原因是认证失败而非权限配置错误,auth::check() 返回 false 表明用户身份未被识别;需优先排查 session 配置、cookie 传递、csrf 校验、guard 设置及 sanctum/passport token 状态等认证环节问题。

Laravel 401 Unauthorized 不是权限配置错,而是认证环节根本没通过——Auth::check() 返回 false,说明框架压根没认出你是谁。
Auth::check() 为什么总返回 false
这是最常被忽略的起点。Laravel 的认证流程在中间件里就卡住了,后续所有逻辑(包括 Policy、Gate)都不会执行。
-
session驱动未启用或配置错误:检查config/session.php中driver是否为file/redis,且对应存储路径/服务可写/可达 - Session Cookie 未正确发送:前端请求遗漏
credentials: 'include'(Fetch)或withCredentials: true(Axios),导致每次都是新会话 - CSRF token 不匹配或缺失:Laravel 默认对非 GET 请求校验
X-XSRF-TOKEN或X-CSRF-TOKEN,失败时直接拒绝,不进认证逻辑,但最终也常表现为 401(尤其在 SPA 场景下) - Guard 名称不一致:自定义 Guard 时,
auth:api中间件默认用apiguard,但config/auth.php里可能只配了web,或guards.api.driver指向了token(已废弃)而非sanctum/passport
Sanctum token 为什么发了也 401
Sanctum 的 token 是存在数据库里的,不是无状态 JWT,所以验证失败往往和数据状态强相关。
- Token 被手动删除或过期:查
personal_access_tokens表,确认该 token 存在、expires_at未过期、abilities包含当前请求所需能力(如['*']或['read']) - Token 未绑定到当前用户:调用
$user->createToken()后,必须把生成的plainTextToken返回给前端,并确保后续请求带的是Bearer {plainTextToken},不是数据库里的哈希值 -
EnsureFrontendRequestsAreStateful中间件漏掉:SPA 调用 API 时,这个中间件负责从 Cookie 提取 session 并关联 Sanctum token,若没加或顺序错,认证直接跳过 - Cookie 域或路径不匹配:前端域名是
app.example.com,但后端SESSION_DOMAIN设成了.example.com或空,导致 Cookie 不携带
Passport client_id/client_secret 报 invalid_client
这个 401 其实来自 OAuth2 授权服务器本身,和用户登录状态无关,是客户端凭据校验失败。
-
client_id不是oauth_clients表的主键 ID:很多开发者误把id字段当 client_id 用,实际应使用clients.id(整数)或clients.password_client生成的 UUID -
client_secret被 URL 编码破坏:Postman/curl 中若未禁用自动编码,+变成空格、/被转义,导致密钥比对失败 - Client 状态为 inactive:表中
personal_access_client或password_client字段为 0,或revoked = 1 - 请求地址错误:向
/oauth/token发 POST 时用了http://(非 HTTPS),而 Passport 强制要求 HTTPS(除非显式关闭Passport::ignoreMigrations()并改源码)
真正容易被忽略的是:Laravel 的 401 往往不是“你没权限”,而是“你连门都没摸到”。先确认 Auth::user() 能否取出用户对象,再查 token 是否有效,最后才看 Policy 或 Gate —— 顺序错了,排查就全偏了。











