jwt认证中间件不生效因laravel默认auth:api不支持jwt,需将guards.api.driver改为jwt并使用jwt.auth中间件;cors头缺失需在异常响应中手动添加或全局中间件兜底;tokencouldnotbecreatedexception源于user未实现jwtsubject接口或getjwtidentifier返回非标量值;refresh失败常因未启用jwt.refresh中间件、黑名单配置不当或前端未更新token。

JWT认证中间件不生效,Auth::check() 总是返回 false
常见现象是接口能跑通、Token 也带了,但 Auth::guard('api')->user() 拿不到用户,本质是 Laravel 没把 JWT 请求路由进认证流程。Laravel 默认的 auth:api 中间件只认 Session 或 Token(即数据库 token),不认 JWT。
必须显式替换 guard 配置,并注册自定义中间件:
- 在
config/auth.php的'guards'下,把'api'的driver改成'jwt'(前提是已安装tymon/jwt-auth) - 确保
app/Http/Kernel.php中$routeMiddleware包含'jwt.auth' => \Tymon\JWTAuth\Middleware\GetUserFromToken::class - 路由中别再用
middleware('auth:api'),改用middleware('jwt.auth')
CORS 头被覆盖,前端提示 No 'Access-Control-Allow-Origin' header
Laravel 自带的 cors 包默认只对预检请求(OPTIONS)加头,而 JWT 认证失败时会直接返回 401 响应——此时中间件链已中断,CORS 头根本没机会写入。结果就是:带 Token 的请求失败,浏览器因缺失 CORS 头直接拦截。
解决方式不是调高中间件顺序,而是让 JWT 错误响应也带上 CORS 头:
- 在
app/Exceptions/Handler.php的render()方法里,对JWTException和子类响应手动添加头:response()->setStatusCode(401)->header('Access-Control-Allow-Origin', '*') - 更稳妥的做法是全局启用 CORS 响应:在
app/Http/Middleware/Cors.php(自建)中对所有响应统一加头,且放在jwt.auth之前 - 避免在
.env里设CORS_ALLOWED_ORIGINS=*后就以为万事大吉——JWT 异常路径绕过 Laravel 的 CORS 中间件,必须单独兜底
JWTAuth::fromUser($user) 报错 TokenCouldNotBeCreatedException
这个异常不是用户不存在,而是 $user 实例没实现 JWTSubject 接口,或 getJWTIdentifier() 返回了非标量值(比如数组或 null)。
检查 App\Models\User 类:
- 必须
use Tymon\JWTAuth\Contracts\JWTSubject并implements JWTSubject -
getJWTIdentifier()只能返回用户主键(通常是$this->getKey()),不能返回$this->id—— 因为 Eloquent 属性访问可能触发延迟加载或转换 -
getJWTCustomClaims()若有,返回值必须是纯数组,且键名不能含点号(.)或空格,否则签名失败
Token 过期后前端刷新失败,JWTAuth::refresh() 返回 401
刷新失败往往不是因为 Token 真过期了,而是请求头里的 Authorization: Bearer <old_token></old_token> 没传进来,或者传的是旧 Token 但服务端已将其加入黑名单(blacklist)但未配置自动清理。
关键动作:
- 确认刷新接口走的是
jwt.refresh中间件(不是jwt.auth),它允许过期 Token 进入逻辑层 - 检查
config/jwt.php中'blacklist_enabled'是否为true;若启用了黑名单,需确保'blacklist_grace_period'足够长(如 60 秒),否则刚过期的 Token 立刻被拉黑,无法刷新 - 前端必须把
refresh()返回的新 Token 替换掉本地存储的旧 Token,否则下次请求仍发旧 Token,必然 401
JWT 的“无状态”是假象——黑名单、刷新窗口、时钟漂移这些细节全靠配置撑着,漏掉一个,跨域认证就变成随机成功。










