跨域报错源于浏览器拦截,401响应缺失cors头因corsfilter在鉴权后执行,异常抛出跳过其逻辑;须在认证类中手动设置响应头,并确保options路由及web服务器支持。

跨域请求报错本身不来自 Yii,而是浏览器拦截后给出的控制台提示——真正要“显示”的,是服务端在 401/403 等认证失败响应中缺失 Access-Control-Allow-Origin 头导致的静默失败。这种情况下,Network 面板里能看到状态码(如 401),但 Response 标签页为空,控制台报 No 'Access-Control-Allow-Origin' header is present。
为什么 401 响应没 CORS 头?
CorsFilter 在 Yii 请求生命周期里位于鉴权之后。当 HttpBearerAuth::authenticate() 抛出 UnauthorizedHttpException,框架直接终止流程、跳过所有行为(包括 CorsFilter),响应头根本没机会写入。
- 现象:正常请求(200)有 CORS 头,401 却没有;Chrome 显示 “Failed to load response data”
- 不是配置漏了,是头根本没走到输出阶段
- Apache/Nginx 层加 header 对 401 无效,因为 PHP 进程都没完整跑完
怎么让 401 响应带上 CORS 头?
必须在认证逻辑内部手动设置响应头,确保它在异常抛出前已写入 $response 对象。
- 新建
common/components/SecureHttpBearerAuth.php,继承yii\filters\auth\HttpBearerAuth - 重写
authenticate()方法,在parent::authenticate()返回null后立刻调用:$response->getHeaders()->set('Access-Control-Allow-Origin', 'https://your-frontend.com') - 同时设
Access-Control-Allow-Credentials和Access-Control-Allow-Headers,值需与前端实际发送的头匹配 - 控制器 behaviors 中改用这个自定义类:
'class' => 'common\components\SecureHttpBearerAuth'
OPTIONS 预检失败时怎么查?
浏览器发 OPTIONS 请求被拒,通常返回 405 或 404,说明路由没捕获到,压根没进 Yii。
- 检查
config/web.php的urlManager.rules顶部是否加了:'OPTIONS *' => 'site/options' - 确认
SiteController::actionOptions()存在且返回null(自动 204)或显式设Yii::$app->response->statusCode = 200 - 用 curl 测试:
curl -X OPTIONS -H "Origin: http://localhost:8080" http://your-api.com/users,看响应头是否含Access-Control-Allow-Origin - 如果连 405 都没看到,可能是 Nginx/Apache 拦截了 OPTIONS,需确认 Web 服务器允许该方法
最易忽略的细节
前后端 Origin 必须完全一致:协议(http/https)、端口(:3000/:8080)、域名(admin.example.com ≠ example.com)缺一不可。哪怕只差一个端口,Access-Control-Allow-Origin: https://admin.example.com 也救不了 http://admin.example.com:3000 的请求。











