laravel 12 中 jwt 认证需手动为异常响应添加 cors 头,因 jwt 异常会绕过默认 cors 中间件;须确保 handlecors 在 jwt.auth 前注册、正确配置 fruitcake/laravel-cors、user 实现 jwtsubject 并校验 token 创建逻辑。

在 Laravel 12 中配置 CORS 时,若同时使用 JWT 认证,不能只依赖默认的 CORS 中间件——因为 JWT 认证失败(如 Token 过期、签名无效、解析异常)会提前中断中间件链,导致响应绕过 CORS 头设置,前端直接报 No 'Access-Control-Allow-Origin' header 错误。关键在于让所有响应(包括认证异常响应)都携带正确的 CORS 头。
确保 fruitcake/laravel-cors 正确启用
安装并注册官方推荐的 CORS 包:
- 运行
composer require fruitcake/laravel-cors - 在
app/Http/Kernel.php的全局中间件数组中加入:\Fruitcake\Cors\HandleCors::class - 发布配置:
php artisan vendor:publish --provider="Fruitcake\Cors\CorsServiceProvider",编辑config/cors.php
生产环境避免设 'allowed_origins' => ['*'],应明确列出可信域名,例如:'allowed_origins' => ['https://app.example.com', 'https://admin.example.com']
JWT 异常响应必须手动补全 CORS 头
Laravel 的 CORS 中间件只对正常流程生效;而 TokenExpiredException、TokenInvalidException 等 JWT 异常由 App\Exceptions\Handler 捕获并返回 401/400 响应,此时 CORS 头尚未写入。
- 打开
app/Exceptions/Handler.php的render()方法 - 对 JWT 相关异常添加头信息:
use Tymon\JWTAuth\Exceptions\JWTException;
if ($exception instanceof JWTException) {
return response()
->json(['error' => 'Unauthorized'], 401)
->header('Access-Control-Allow-Origin', 'https://app.example.com')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
->header('Access-Control-Allow-Headers', 'Authorization, Content-Type, X-Requested-With');
}
路由中间件顺序与 jwt.auth 的正确使用
CORS 中间件必须在 JWT 认证中间件之前执行,否则预检请求(OPTIONS)可能被 jwt.auth 拦截而无法到达 CORS 层。
- 确认
app/Http/Kernel.php中\Fruitcake\Cors\HandleCors::class位于'jwt.auth'之前 - API 路由不要用
middleware('auth:api'),它不识别 JWT;改用middleware('jwt.auth') - 确保
config/auth.php中guards.api.driver已设为'jwt',且对应 provider 正确指向'users'
User 模型实现 JWTSubject 是前提
如果 JWTAuth::attempt() 报 TokenCouldNotBeCreatedException,即使 CORS 配置再完善,登录也失败,自然无 Token 可传。
- 检查
App\Models\User是否 implementsJWTSubject -
getJWTIdentifier()必须返回标量值(如$this->id),不可返回null或数组 -
getJWTCustomClaims()返回的自定义字段不宜含敏感数据,且结构需 JSON 可序列化











