Laravel中用Http-only Cookie+Axios访问受保护路由遇401问题
1. 修改JWT认证逻辑,从Http-only Cookie读取Token
默认的auth:api中间件只会从Authorization请求头解析JWT Token,不会自动读取Cookie。你需要自定义认证逻辑,让Laravel优先从auth_token Cookie中获取Token:
方法一:自定义JWT Guard
在app/Providers/AuthServiceProvider.php的boot方法中注册自定义Guard:
use Illuminate\Support\Facades\Auth; use Tymon\JWTAuth\JWTGuard; public function boot() { $this->registerPolicies(); Auth::extend('jwt-cookie', function ($app, $name, array $config) { $guard = new JWTGuard( $app['tymon.jwt'], Auth::createUserProvider($config['provider']), $app['request'] ); // 让Guard优先从Cookie获取Token, fallback到Bearer Token $guard->getJWTProvider()->setParser(function ($request) { return $request->cookie('auth_token') ?: $request->bearerToken(); }); $app->refresh('request', $guard, 'setRequest'); return $guard; }); }
然后在config/auth.php中更新guards配置,替换默认的api驱动:
'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'jwt-cookie', // 使用自定义的guard驱动 'provider' => 'users', ], ],
方法二:手动在中间件解析Cookie
如果不想自定义Guard,也可以在认证中间件中手动从Cookie取Token验证:
// 新建或修改app/Http/Middleware/AuthenticateWithCookie.php use Closure; use Tymon\JWTAuth\Facades\JWTAuth; use Illuminate\Support\Facades\Auth; class AuthenticateWithCookie { public function handle($request, Closure $next) { try { $token = $request->cookie('auth_token'); if (!$token) { throw new \Tymon\JWTAuth\Exceptions\TokenNotFoundException(); } $user = JWTAuth::setToken($token)->authenticate(); Auth::login($user); } catch (\Exception $e) { return response()->json(['message' => 'Unauthorized'], 401); } return $next($request); } }
之后在路由或控制器中用这个中间件替换原来的auth:api。
2. 完善CORS全局配置
不要在登录响应中硬写CORS头,用Laravel CORS包做全局配置更可靠:
- 确保
config/cors.php配置正确:
return [ 'paths' => ['api/*', 'request.json', 'action.json'], 'allowed_methods' => ['*'], 'allowed_origins' => ['http://localhost:5173'], 'allowed_headers' => ['Content-Type', 'X-Requested-With'], 'supports_credentials' => true, // 必须开启,允许跨域携带Cookie 'max_age' => 3600, ];
- 确认
app/Http/Kernel.php的api中间件组包含CORS处理中间件:
protected $middlewareGroups = [ 'api' => [ \Fruitcake\Cors\HandleCors::class, 'throttle:api', \Illuminate\Routing\Middleware\SubstituteBindings::class, ], ];
3. 检查Cookie参数配置
登录时设置的Cookie参数要符合跨域要求:
$cookie = Cookie::make( 'auth_token', $token, 60, // 有效期(分钟) '/', // 路径设为/,确保全站点路由都能访问到Cookie null, // 本地开发domain留空即可,生产环境填对应域名 env('APP_ENV') !== 'local', // 生产环境开启HTTPS时设为true true, // 保持HttpOnly为true false, 'Lax' // 跨域场景下如果Strict无效,可尝试改为Lax );
4. 调试验证步骤
- 打开浏览器开发者工具Network标签,检查请求的Request Headers中是否包含
Cookie: auth_token=xxx,且Response Headers中Cookie的HttpOnly标记为true - 在受保护路由中临时打印
dd($request->cookie('auth_token')),确认Laravel能获取到Cookie值 - 用
JWTAuth::setToken($token)->check()验证Token是否有效
内容的提问来源于stack exchange,提问作者bright-webb
相关产品推荐
相关产品推荐

