Laravel 8集成Sanctum跨子域部署偶发CORS错误咨询
偶发CORS错误核心原因
三个配置问题叠加导致该现象:
- CORS配置违反规范:开启
supports_credentials跨域凭证携带时,allowed_origins设置为通配符*,不符合浏览器CORS安全规则,且旧版fruitcake/cors扩展在该配置组合下存在偶发响应头错误的bug,直接导致时好时坏、多环境状态互换的现象 - Sanctum中间件缺失:API中间件组未加入Sanctum的状态化请求校验中间件,被限流、鉴权拦截的请求不会经过CORS头注入逻辑,返回的401/429响应会被浏览器判定为跨域错误
- 环境域名配置不匹配:两套部署环境的会话共享域名、Sanctum可信域名未对应配置,导致偶发cookie鉴权失败,触发无CORS头的异常响应
修复步骤
1. 修正CORS配置文件
修改config/cors.php,移除通配符源配置,明确写入所有允许的前端域名:
'paths' => ['api/*', 'sanctum/csrf-cookie'], 'allowed_methods' => ['*'], // 替换原allowed_origins的['*']配置 'allowed_origins' => [ 'https://domain.com', 'https://dev.domain.com', // 如果存在www.domain.com等其他前端访问地址,一并完整加入 ], 'allowed_origins_patterns' => [], 'allowed_headers' => ['*'], 'exposed_headers' => [], 'max_age' => 0, 'supports_credentials' => true,
注意:配置允许源时必须带完整协议头(http/https),有非80/443端口的还要加端口号,不能省略。
2. 补全API中间件组配置
修改app/Http/Kernel.php,在api中间件组的最顶部加入Sanctum状态化请求中间件,确保所有API请求(包括OPTIONS预检请求)优先经过CORS和Sanctum认证逻辑:
'api' => [ // 新增以下行,必须放在该组最开头 \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, 'throttle:api', \Illuminate\Routing\Middleware\SubstituteBindings::class, ],
3. 按环境匹配配置变量
分别修改预发布、生产环境的.env文件,填入对应环境的域名配置,不能共用一套配置:
生产环境(前端domain.com / 后端api.domain.com)
SANCTUM_STATEFUL_DOMAINS=domain.com,api.domain.com SESSION_DOMAIN=.domain.com
预发布环境(前端dev.domain.com / 后端devapi.domain.com)
SANCTUM_STATEFUL_DOMAINS=dev.domain.com,devapi.domain.com SESSION_DOMAIN=.dev.domain.com
注意:
SESSION_DOMAIN前的点不能省略,该配置用于实现同根域名下的跨子域cookie共享。如果前端通过www子域名访问,需要把对应www域名也加入SANCTUM_STATEFUL_DOMAINS列表。
4. 清理配置缓存
所有修改完成后,在两套环境分别执行以下命令,清除旧配置缓存:
php artisan config:clear php artisan route:clear php artisan cache:clear
补充排查点
如果完成以上配置后仍存在偶发错误,逐一检查以下项:
- 前端请求库(如axios)是否开启了
withCredentials: true配置,未开启时跨域请求不会携带cookie,会被Sanctum拦截返回401 - 检查Web服务器(Nginx/Apache)配置,不要在服务层重复添加CORS响应头,避免和Laravel返回的头冲突
- 确认异常处理逻辑没有提前终止响应:当接口返回401、429、500等错误码时,检查响应头是否包含正确的CORS字段,若缺失则说明请求未经过全局CORS中间件处理,需要调整异常处理器逻辑
内容的提问来源于stack exchange,提问作者jerome gallego
相关产品推荐
相关产品推荐

