Laravel怎么实现JWT认证_Laravel API Token鉴权教程【无状】

1次阅读

jwt认证在laravel中需手动配置guard、provider及Token签发/解析逻辑,非开箱即用;auth::user()在api路由中为NULL主因是guard未正确切换至jwt或sanctum,且api中间件组误含startsession;token须存客户端并以authorization: bearer xxx格式传递,过期需结合refresh机制与黑名单校验。

Laravel怎么实现JWT认证_Laravel API Token鉴权教程【无状】

JWT认证在Laravel里不是开箱即用的

Laravel自带的 Auth::attempt() 和 Session 认证不生成 JWT,直接装个包就以为能用 Auth::user() 拿到登录用户?大概率 401 或 null。JWT 是无状态的,得自己接管 token 的签发、解析、刷新逻辑,Laravel 的 guard 和 provider 也得重配。

常见错误现象:Call to undefined method IlluminateAuthRequestGuard::login()(想调 login() 却没实现)、Token has expired(没配 exp 或没刷新)、Unauthenticated(中间件没识别 Bearer 头)。

  • 别用 php artisan make:auth —— 它只配 Session,和 JWT 冲突
  • 推荐用 tymon/jwt-auth(v2.x 支持 Laravel 9+),但注意它已停止维护;更稳妥选 laravel/sanctum(适合 API + SPA)或纯手写 firebase/php-jwt(轻量、可控)
  • 如果坚持用 tymon/jwt-auth,必须运行 php artisan vendor:publish --provider="TymonJWTAuthProvidersLaravelServiceProvider" 并手动改 config/jwt.php 中的 secret(别用默认值!)

如何让 login 接口返回 JWT 而不是跳转或 Session

默认 Auth::attempt() 只返回 bool,JWT 需要显式签发 token。关键不是“怎么登录”,而是“登录成功后怎么生成、返回、存 token”。

使用场景:APP 或前端调 /api/login,期望响应体含 {"token": "xxx"},后续请求带 Authorization: Bearer xxx

  • 别在控制器里直接写 JWTAuth::fromUser($user) —— 如果没提前配置好 guard,会抛 JWTException
  • 先确保 config/auth.php'defaults' => ['guard' => 'api'],且 'guards'['api']['driver'] 设为 jwt(用 tymon)或 sanctum(用 sanctum)
  • login 方法示例(tymon):
    use TymonJWTAuthFacadesJWTAuth;  public function login(Request $request) {     $credentials = $request->only('email', 'password');     if (!$token = JWTAuth::attempt($credentials)) {         return response()->json(['error' => 'Unauthorized'], 401);     }     return response()->json(compact('token')); }
  • 注意:tymon v2.x 默认不支持 refresh,如需自动续期,得加 refresh 接口并设 ttlrefresh_ttl(单位分钟)

为什么 Auth::user() 在 API 路由里总是 null

因为 Laravel 默认的 web guard 依赖 session cookie,而 API 请求通常没 cookie,也不走 session 启动流程。哪怕 token 正确,guard 没被正确调用,Auth::user() 就是 null。

参数差异:Session guard 查 session_id(),JWT guard 查 Authorization header 里的 Bearer token 并解码验证签名。

  • 确认路由用了 api 中间件组:Route::middleware('api')->group(...),而不是 web
  • 检查 app/http/Kernel.php'api' 中间件组是否包含 IlluminateSessionMiddlewareStartSession::class —— API 路由里必须删掉它,否则 session 启动会干扰 JWT 解析
  • 若用 sanctum,确保模型用了 HasApiTokens trait,且 config/sanctum.phpstateful 域名不含你的 API 前端(比如 localhost:5173 不该在 stateful 列表里)
  • 调试技巧:在中间件里 dump request()->header('Authorization')JWTAuth::parseToken()->authenticate() 看哪步失败

token 存哪?前端怎么传?过期了怎么办

JWT 是客户端存储的凭证,服务端只校验,不保存。存错地方或传错格式,立刻 401。

性能影响:每次请求都 decode + verify signature + 检查 exp,比 session id 查 redis 略重,但可接受;兼容性上,IE 不支持 fetchheaders 设置,老项目得用 XMLHttpRequest

  • 前端存 token 推荐 localStorage(方便调试),但 xss 风险高;更安全用 httpOnly cookie(需后端 set-cookie,且跨域要配 withCredentials: true
  • 传 token 必须是 Authorization: Bearer <token></token>,少一个空格、多一个引号、漏 Bearer 前缀都会失败 —— 后端解析时 request()->bearerToken() 就拿不到
  • 过期处理不能只靠前端倒计时:服务端要校验 exp 字段,且建议加 nbf(not before)防重放;刷新 token 时,旧 token 应加入黑名单(tymon 提供 invalidate(),但需自己存黑名单位置)
  • 别把 refresh token 和 access token 存一起 —— refresh token 要更长 ttl、更严校验(比如绑定 user agent / IP)

最常被忽略的是:JWT 的 sub(subject)字段默认是用户 ID,但如果用户被软删除或禁用,JWTAuth::parseToken()->toUser() 仍会返回模型实例。得在 User 模型里重写 getJWTIdentifier() 或加中间件做二次校验。

text=ZqhQzanResources