【问题标题】:Yii2 + restapi + cors + bearer - unauthorized when creating custom controller actionYii2 + restapi + cors + bearer - 创建自定义控制器操作时未经授权
【发布时间】:2017-08-08 18:19:46
【问题描述】:

我正在制作 Angular 2 / Yii2 应用程序

当我使用不记名标头从 Postman 调用自定义控制器/操作时,一切正常,但是当我使用 angular 2 应用程序 (localhost:4200) 中的相同标头调用它时,我总是收到未经授权的 401 错误。 当我从guide 的示例中执行标准操作时,例如:

GET /users: list all users page by page;
POST /users: create a new user;

一切正常,只有当我创建自定义操作时,才会获得未经授权。

这是跨域应用, angular 可在 web.example.com 上找到, yii2 应用在 srv.example.com 上

namespace app\controllers\restapi;

use yii\filters\auth\CompositeAuth;
use yii\filters\auth\HttpBearerAuth;

class SearchOrderController extends \yii\rest\Controller
{
    public $modelClass = 'app\models\Order';
    public function behaviors()
    {
        $behaviors = parent::behaviors();
        $auth = $behaviors['authenticator'];
        unset($behaviors['authenticator']);
        $behaviors['corsFilter'] = [
                'class' => \yii\filters\Cors::className(),
        ];
        $behaviors['authenticator'] = [
                'class' => CompositeAuth::className(),
                'authMethods' => [
                        HttpBearerAuth::className(),
                ],
        ];
        // avoid authentication on CORS-pre-flight requests (HTTP OPTIONS method)
        return $behaviors;
    }
    public function actionSearch(){
        \Yii::$app->response->format=\yii\web\Response::FORMAT_JSON;
        return ['index'=>'some text', 'value'=>123];
    }
}

也是我的网址管理器:

        [
            'class' => 'yii\rest\UrlRule',
            'controller' => 'order',
            'pluralize' => false,
            'extraPatterns' => [
                'GET order/<id:\id+>' => 'order/view',
            ]
        ],
        [
            'class' => 'yii\rest\UrlRule',
            'controller' => 'search-order',
            'pluralize' => false,
            'extraPatterns' => [
                'GET search-order/search' => 'search-order/search',
        ]

【问题讨论】:

  • 你确定 GET 和 POST 是失败的请求吗?您能否检查一下您浏览器的网络选项卡,看看它是否不是失败的OPTIONS /users
  • 这是选项...因为我收到的消息是:选项srv.example.com/restapi/search-order/search 401(未经授权)我该怎么办?
  • 此问题的official solution

标签: rest yii2 cors


【解决方案1】:

我已经使用此处发布的解决方案解决了我的问题:

Yii2 Rest - Custom action and OPTIONS method

并实现自定义 Cors 类:

<?php 
namespace app\components;

use Yii;
use yii\filters\Cors;

class CustomCors extends  Cors

{
    public function beforeAction($action)
    {
        parent::beforeAction($action);

        if (Yii::$app->getRequest()->getMethod() === 'OPTIONS') {
            Yii::$app->getResponse()->getHeaders()->set('Allow', 'POST GET PUT');
            Yii::$app->end();
        }

        return true;
    }
}

并相应地改变我的控制器行为:

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

        // remove authentication filter
        $auth = $behaviors['authenticator'];
        unset($behaviors['authenticator']);

        // add CORS filter
        $behaviors['corsFilter'] = [
                'class' =>CustomCors::className()
        ];

        // re-add authentication filter
        $behaviors['authenticator'] = [
                'class' => CompositeAuth::className(),
                'authMethods' => [
                        HttpBearerAuth::className(),
                ],

        ];

        return $behaviors;
   }

【讨论】:

    【解决方案2】:

    看起来这是一个preflight request 问题。我在这里看到两件事要解决。

    首先,您需要在扩展yii\rest\Controller 时执行一个操作来响应该请求。这样的操作is already implemented by Yii 但在其子控制器yii\rest\ActiveController 中。因此,您可以使用actions() 函数像here 那样导入它,也可以像在其他satck 溢出帖子中那样直接实现它:

    Post Request working in Postman but returns Preflight error in Angular 2 app

    然后你需要定义它们的相关规则:

    [
        'class' => 'yii\rest\UrlRule',
        'controller' => 'order',
        'pluralize' => false,
        'extraPatterns' => [
            'GET order/<id:\id+>' => 'order/view',
            'OPTIONS order/<id:\id+>' => 'order/options',
        ]
    ],
    [
        'class' => 'yii\rest\UrlRule',
        'controller' => 'search-order',
        'pluralize' => false,
        'extraPatterns' => [
            'GET search-order/search' => 'search-order/search',
            'OPTIONS search-order/search' => 'search-order/options',
    ]
    

    接下来,您需要让您的身份验证允许预检请求,因为浏览器不会向它们发送任何令牌。通过添加这一行,如official docs:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-24
      • 2021-09-21
      • 1970-01-01
      • 1970-01-01
      • 2015-02-20
      • 2022-01-25
      相关资源
      最近更新 更多