【问题标题】:yii2 restful api: (Reason: CORS header ‘Access-Control-Allow-Origin’ missing)yii2 restful api:(原因:缺少 CORS 标头“Access-Control-Allow-Origin”)
【发布时间】:2021-02-16 03:17:01
【问题描述】:

我想将 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).

但是当我在 Firefox 开发者工具中检查 network 时,我发现 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' => ['*'],
            ],

        ],
    ];
}

但报错

Invalid Argument – yii\base\InvalidArgumentException 响应内容 不能是数组。

我该如何解决这个问题?

【问题讨论】:

  • 那么当前的问题是什么是无效参数的例外?
  • React 无法得到 rest 响应并得到错误 'Cross-Origin Request Blocked...'
  • 添加行为后,我得到 Invalid Argument 错误

标签: reactjs rest yii2


【解决方案1】:

更新

更新了答案,因为实现的逻辑是允许每个请求通过身份验证过滤器(感谢@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()


根据docs,您应该首先取消设置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;
    }

}

【讨论】:

  • 此解决方案有效。但是我注意到在这个解决方案之后,每个 url/方法都可以通过选项请求访问。及其提供数据,例如经过身份验证的用户。所以请进行安全检查。
  • @KalyanHalderRaaz ,是的,你是对的,这确实允许,我用原因更新了答案并修复,请在你最后更新
【解决方案2】:

另一种可能的解决方案是定义一个虚拟主机。当我将 API URL 设置为 http://localhost:8080/ 或 http://127.0.0.1:8080/

时,我遇到了类似的问题

通过在 XAMMP 中定义虚拟主机并将其映射到 127.0.0.1,问题就解决了。

【讨论】:

    猜你喜欢
    • 2020-11-12
    • 1970-01-01
    • 2021-01-25
    • 2018-03-28
    • 2021-02-11
    • 2019-02-07
    • 2017-01-09
    • 2021-07-15
    • 1970-01-01
    相关资源
    最近更新 更多