子域名下Laravel Sanctum+ReactJS SPA跨域CORS错误求助
Laravel Sanctum跨域登录CORS错误排查与解决
问题背景
已花费5天时间尝试解决跨域问题,API部署在api.mydomain.edu.af,SPA部署在spa.mydomain.edu.af。能正常通过sanctum/csrf-cookie接口获取XSRF-Token,但调用登录接口api.mydomain.edu.af/api/login(定义在api.php)时触发CORS错误。
相关配置及请求详情
1. .env配置
SANCTUM_STATEFUL_DOMAINS=mydomain.edu.af SESSION_DOMAIN=.mydomain.edu.af
2. Kernel.php中间件组配置
protected $middlewareGroups = [ 'web' => [ \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, // \Illuminate\Session\Middleware\AuthenticateSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\VerifyCsrfToken::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, ], 'api' => [ \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, 'throttle:api', \Illuminate\Routing\Middleware\SubstituteBindings::class, ], ];
3. cors.php配置
'paths' => ['api/*', 'sanctum/csrf-cookie'], 'allowed_methods' => ['*'], 'allowed_origins' => ['*'], 'allowed_origins_patterns' => [], 'allowed_headers' => ['*'], 'exposed_headers' => [], 'max_age' => 0, 'supports_credentials' => true,
4. sanctum.php配置
'stateful' => explode(',', env( 'SANCTUM_STATEFUL_DOMAINS', 'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1,'.parse_url(env('APP_URL'), PHP_URL_HOST) )),
5. ReactJS Axios登录请求(已成功获取csrf-cookie)
axios.defaults.withCredentials = true; await axios .post(global.config.main.Api_Url + "/api/login", postData, { headers: { Accept: "application/json" }, }) .then((response) => { if (response.status === 200) { signIn({ token: response.data["token"], expiresIn: 3600, tokenType: "Bearer", authState: { firstname: response.data["firstname"] }, }); } else { setError("Something Went Wrong!"); } });
解决方案
1. 修正SANCTUM_STATEFUL_DOMAINS配置
将.env中的SANCTUM_STATEFUL_DOMAINS改为包含SPA域名:
SANCTUM_STATEFUL_DOMAINS=spa.mydomain.edu.af,api.mydomain.edu.af
Sanctum需要明确指定所有允许的有状态前端域名,仅填根域名可能无法识别子域名的SPA请求。
2. 检查APP_URL配置
确保.env中的APP_URL指向API域名:
APP_URL=https://api.mydomain.edu.af
sanctum.php中会自动读取该值加入状态域名列表,避免遗漏。
3. 确认CORS中间件优先级
确保HandleCors中间件在Kernel.php的$middleware数组最顶部加载,优先级高于其他中间件:
protected $middleware = [ \Illuminate\Http\Middleware\HandleCors::class, // 放在最前面 \App\Http\Middleware\TrustProxies::class, // ...其他中间件 ];
如果CORS中间件加载过晚,可能在其他中间件处理请求前未正确设置跨域头。
4. 验证XSRF-Token是否正确携带
在Axios请求中手动添加X-XSRF-TOKEN头,确保Cookie中的XSRF-Token被正确传递:
await axios .post(global.config.main.Api_Url + "/api/login", postData, { headers: { Accept: "application/json", 'X-XSRF-TOKEN': decodeURIComponent(document.cookie.match(/XSRF-TOKEN=([^;]+)/)[1]) }, })
部分环境下Axios可能无法自动读取并携带该头,手动添加可避免验证失败触发的CORS类错误。
5. 清除缓存并重启服务
修改配置后执行以下命令清除缓存:
php artisan config:clear php artisan cache:clear
重启PHP-FPM和Web服务器(如Nginx/Apache),确保新配置生效。
内容的提问来源于stack exchange,提问作者Hedayatullah Hedayat
相关产品推荐
相关产品推荐

