You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何配置Nginx代理服务器CORS,使React应用可访问Yii2 REST API

问题排查与解决方案

核心问题分析

你遇到的是部分API接口CORS正常、仅/v1/auth/login接口预检请求失败的问题,结合配置细节,根源大概率出在OPTIONS预检请求的处理逻辑、Yii2鉴权排除规则的准确性或CORS头的一致性配置上。

问题根源排查方向

  1. Nginx的CORS配置未覆盖OPTIONS请求:login是POST请求,会触发浏览器的OPTIONS预检,若Nginx未针对OPTIONS请求返回完整CORS头,或配置的路由范围不包含/v1/auth/login,就会报错。
  2. Yii2的OPTIONS请求未被正确放行:虽然你排除了login和options接口的JWT鉴权,但可能路由匹配规则有误,导致OPTIONS请求仍被鉴权拦截,返回的响应缺少CORS头。
  3. withCredentials的头配置冲突:启用withCredentials后,Access-Control-Allow-Origin不能设为*,必须指定具体前端域名,若login接口的响应头不符合此规则,会触发错误。

分步解决方案

1. 修正Nginx的CORS配置,确保覆盖所有接口

在API的Nginx server块中添加完整的CORS规则,重点处理OPTIONS预检请求,同时保证所有请求都带上正确的头:

server {
    listen 443 ssl;
    server_name api.example.com;

    # 全局CORS头配置(必须加always,确保非200状态码也能返回头)
    add_header Access-Control-Allow-Origin "https://your-react-frontend.com" always;
    add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always;
    add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
    add_header Access-Control-Allow-Credentials "true" always;

    # 直接处理OPTIONS预检请求,返回204(无需转发到Yii2)
    if ($request_method = OPTIONS) {
        return 204;
    }

    # Yii2入口路由配置
    location / {
        try_files $uri $uri/ /index.php$is_args$args;
        # 其他fastcgi配置...
    }

    # 若login接口有单独location,需确保CORS头在此处也生效
    # location /v1/auth/login {
    #     add_header ... (同上CORS配置)
    #     try_files $uri $uri/ /index.php$is_args$args;
    # }
}

注意:Access-Control-Allow-Origin必须设置为你的前端实际域名,不能用*。

2. 确认Yii2鉴权与CORS过滤器配置

检查AuthController的behaviors()方法,确保OPTIONS请求和login接口被正确排除,同时启用Yii2的CORS过滤器(避免和Nginx配置冲突):

use yii\filters\Cors;
use yii\filters\auth\HttpBearerAuth;

public function behaviors()
{
    $behaviors = parent::behaviors();

    // 移除默认鉴权,替换为JWT鉴权
    unset($behaviors['authenticator']);
    $behaviors['authenticator'] = [
        'class' => HttpBearerAuth::class,
        'except' => ['login', 'options'], // 确保options和login动作被排除
    ];

    // 启用CORS过滤器,配置需和Nginx保持一致
    $behaviors['corsFilter'] = [
        'class' => Cors::class,
        'cors' => [
            'Origin' => ['https://your-react-frontend.com'],
            'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
            'Access-Control-Allow-Credentials' => true,
            'Access-Control-Max-Age' => 3600,
        ],
    ];

    return $behaviors;
}

验证:确保路由v1/auth/login对应的action是login,避免因路由映射错误导致鉴权未排除。

3. 验证Axios配置一致性

确保Axios全局配置的withCredentials为true,且请求域名与CORS头中的域名完全匹配:

import axios from 'axios';

axios.defaults.withCredentials = true;
axios.defaults.baseURL = 'https://api.example.com/v1';

// 登录请求示例
axios.post('/auth/login', {
  username: 'your-username',
  password: 'your-password'
})
.then(res => console.log(res))
.catch(err => console.error(err));

4. 测试预检请求

用curl手动发送OPTIONS请求到login接口,检查响应头是否包含正确的CORS字段:

curl -I -X OPTIONS https://api.example.com/v1/auth/login

正常响应应包含:

Access-Control-Allow-Origin: https://your-react-frontend.com
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS

内容的提问来源于stack exchange,提问作者sam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 14:20:28