Yii2.0.50中配置API跨域需三步:一是在web/index.php入口添加全局CORS响应头;二是为REST控制器配置yii\filters\Cors行为;三是重写beforeAction支持OPTIONS预检请求。

在Yii2.0.50中为前后端分离项目配置API跨域(CORS),核心是让后端接口响应中包含正确的Access-Control-Allow-*头部,使前端Vue/React应用能从localhost:8080等非同源地址安全调用localhost:8000的API。不配置会导致浏览器拦截请求并报错“has been blocked by CORS policy”。
修改入口文件web/index.php添加全局CORS头
打开web/index.php,在require __DIR__ . '/../vendor/autoload.php';之后、(new yii\web\Application($config))->run();之前插入以下代码:
header('Access-Control-Allow-Origin: http://localhost:8080');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');
header('Access-Control-Allow-Credentials: true');
这一步必须放在Application实例化之前,否则headers会被Yii内部响应对象覆盖。若前端部署在其他域名(如https://admin.example.com),请将Origin值同步替换,【Origin值不可写成*配合Credentials:true】,否则浏览器会直接拒绝响应。
为RESTful API模块单独配置CORS行为
若项目已启用yii\rest\ActiveController或自定义REST模块,推荐在控制器类中声明behaviors:
在控制器(如controllers/Api/V1/UserController.php)的behaviors()方法内添加:
方法一:使用yii\filters\Cors过滤器
'cors' => [
'class' => \yii\filters\Cors::className(),
'cors' => [
'Origin' => ['http://localhost:8080'],
'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
'Access-Control-Request-Headers' => ['*'],
'Access-Control-Allow-Credentials' => true,
],
],
该配置会自动处理预检(OPTIONS)请求,无需额外路由映射。注意:若同时在web/index.php和控制器中设置CORS,以控制器为准,避免重复响应头冲突。
处理预检OPTIONS请求的终极方案
当遇到复杂请求(如带Authorization头或Content-Type为application/json)时,浏览器会先发OPTIONS请求。Yii2默认不响应OPTIONS,需显式支持:
第一步:在config/web.php的components中注册URL规则
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
['pattern' => '<controller:>/<action:>', 'route' => '<controller>/<action>'],</action></controller></action:></controller:>
['pattern' => 'api/<module:>/<controller:>', 'route' => 'api/<module>/<controller>'],</controller></module></controller:></module:>
],
],
第二步:在对应控制器(如controllers/ApiController.php)中重写beforeAction()
public function beforeAction($action)
{
if ($this->request->getMethod() === 'OPTIONS') {
return true;
}
return parent::beforeAction($action);
}
第三步:确保控制器继承yii\rest\Controller而非yii\web\Controller,否则OPTIONS响应体为空,浏览器仍会报错。


















