首页 > 解决方案 > yii2 restful api:(原因:缺少 CORS 标头“Access-Control-Allow-Origin”)

问题描述

我想将 React 与 Yii2 RESTful 一起使用,我创建了一个这样的用户控制器:

<?php
namespace app\controllers;
use yii\rest\ActiveController;

class UsersController extends ActiveController
{
    public $modelClass = 'app\models\User';
}

当浏览器中的打开链接显示我的用户时,当我想axios在反应中使用时,我在浏览器控制台中收到错误:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost/rest/web/users. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).

但是当我检查networkFirefox 开发者工具时,我发现 axios 请求和它的状态为 200 并正确接收响应。

我尝试behaviors在我的控制器中使用功能,如下所示:

public function behaviors()
{
    return [
        'corsFilter' => [
            'class' => \yii\filters\Cors::className(),
            'cors' => [
                'Origin' => ['*'],
                'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
                'Access-Control-Request-Headers' => ['*'],
            ],

        ],
    ];
}

但得到错误

无效参数 – yii\base\InvalidArgumentException 响应内容不能是数组。

我该如何解决这个问题?

标签: reactjsrestyii2

解决方案


更新

更新了答案,因为实现的逻辑是允许每个请求通过身份验证过滤器(感谢@KalyanHalderRaaz指出错误)。

有两件事要改变

  • 重新添加过滤器时,最好指定您正在使用的身份验证。更改下面的代码

    // re-add authentication filter
    $behaviors['authenticator'] = $auth;
    

    以下,我正在使用BasicAuth例如。

    $behaviors['authenticator'] = [
        'class' => yii\filters\auth\HttpBasicAuth::class
    ];
    
  • 添加时beforeAction()不要忘记包装逻辑,if(parent::beforeAction($action))否则它将验证每个请求,因为我们只是true在这里为每个请求返回并且也不会调用会触发过滤器的父级。

    替换beforeAction()为以下

    public function beforeAction($action)
    {
        if (parent::beforeAction($action)) {
            \Yii::$app->response->format = Response::FORMAT_JSON;
            return true;
        }
    
    }
    

只需确保您覆盖findIdentityByAccessToken()用户身份模型中的


根据文档,您应该首先取消设置authenticator过滤器以添加Cors过滤器,因此您的行为应该看起来像

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

    // remove authentication filter necessary because we need to 
    // add CORS filter and it should be added after the CORS
    unset($behaviors['authenticator']);

    // add CORS filter
    $behaviors['corsFilter'] = [
        'class' => '\yii\filters\Cors',
        'cors' => [
            'Origin' => ['*'],
            'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
            'Access-Control-Request-Headers' => ['*'],
        ],
    ];

    // re-add authentication filter of your choce
    $behaviors['authenticator'] = [
        'class' => yii\filters\auth\HttpBasicAuth::class
    ];

    // avoid authentication on CORS-pre-flight requests (HTTP OPTIONS method)
    $behaviors['authenticator']['except'] = ['options'];
    return $behaviors;
}

您可以通过添加beforeAction以下内容将响应格式设置为控制器内的 json

public function beforeAction($action)
{
    if (parent::beforeAction($action)) {
        \Yii::$app->response->format = Response::FORMAT_JSON;
        return true;
    }

}

推荐阅读