具有Auth的Yii2 CORS不适用于非CRUD操作

时间:2016-03-29 01:56:00

标签: php rest yii2 cors

我正在Yii2中构建API并添加了CORS和身份验证。这适用于所有创建/读取/更新/删除操作,但不适用于自定义操作。有没有人经历过这个?

网址管理员:

        tableLayoutPanel1.Controls.Add(new LinkLabel() { Text = "TEST",Name = count.ToString(),Tag = @"N:\reuther", Anchor = AnchorStyles.Left, AutoSize = true }, 2, 3);

控制器行为:

['class' => 'yii\rest\UrlRule', 'controller' => 'api/v1/user', 'pluralize' => false],

如上所述,CRUD的操作很好,但public function behaviors() { return ArrayHelper::merge([ 'corsFilter' => [ 'class' => Cors::className(), ], [ 'class' => HttpBearerAuth::className(), 'except' => ['options', 'login', ], ], ], parent::behaviors() ); } 等自定义操作会响应http://domain.com/user/test响应。

是否无法让CORS和auth在自定义操作上协同工作?

编辑:我应该补充一点,只有当浏览器发出401 Unauthorised请求时才会出现问题(401)。正常请求(curl,Postman)不受影响。 RESTful,Cors,Auth组合似乎会出现这个问题。

2 个答案:

答案 0 :(得分:8)

试试这个:

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

    unset($behaviors['authenticator']);

    $behaviors['corsFilter'] = [
        'class' => Cors::className(),
        'cors' => [
            'Origin' => ['*'],
            'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
            'Access-Control-Request-Headers' => ['*'],
            'Access-Control-Allow-Credentials' => true,
        ],
    ];

    $behaviors['authenticator'] = [
        'class' =>  HttpBearerAuth::className(),
        'except' => ['options','login'],
    ];

    return $behaviors;
}

取消设置 parent controller实施的默认authenticator,以确保首先处理cors。然后,在实施您自己的cors之前,我们会强制authenticator允许凭据。

另一件可能引发未经授权错误的事情是未找到或错误Options响应,因为浏览器首先要求获取允许动词列表。您可以在浏览器的网络标签中检查其标题响应中的列表。

一般规则是,当您要求浏览器对任何网址执行PUT,DELETE或POST等敏感动词时,它可能会先向同一网址发送OPTIONS请求 check this )在发送真实请求之前检查是否允许该动词。所以Yii应该配置为通过执行正确的重定向来响应所有这些OPTIONS动词。

ActiveController实施的默认CRUD操作正在使用default patterns

'PUT,PATCH {id}' => 'update',
'DELETE {id}' => 'delete',
'GET,HEAD {id}' => 'view',
'POST' => 'create',
'GET,HEAD' => 'index',
'{id}' => 'options',
'' => 'options',

因此,您在urlManager['rules']中实现的任何配置都要确保不覆盖它们中的最后两个,如果您使用自定义模式,请始终记住包含其等效的options动词,如下例所示:< / p>

[
    'class' => 'yii\rest\UrlRule', 
    'controller' => ['account' => 'auth/account'], 
    'patterns' => [
        'POST,HEAD login'  => 'login',
        'POST,HEAD signup' => 'signup',
        'POST req-reset-pass' => 'request-password-reset',
        'POST reset-pass' => 'reset-password',
        // OPTTIONS VERBS
        'OPTIONS login' => 'options',
        'OPTIONS signup' => 'options',
        'OPTIONS req-reset-pass' => 'options',
        'OPTIONS reset-pass' => 'options',
    ]
],

extraPatterns 中添加自定义模式时也是如此。

Options默认情况下会在ActiveController中实施ActiveController操作。可以看到它的代码here。 如果您正在扩展与\yii\rest\Controller不同的控制器,例如public function actions() { $actions = parent::actions(); $actions['options'] = [ 'class' => 'yii\rest\OptionsAction', // optional: 'collectionOptions' => ['GET', 'POST', 'HEAD', 'OPTIONS'], 'resourceOptions' => ['GET', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'], ]; return $actions; } ,请确保手动包含它:

var myApp = angular.module('myApp', []);

myApp.directive("datepicker", function () {
  return {
    restrict: "A",
    require: "ngModel",
    link: function (scope, elem, attrs, ngModelCtrl) {
      var updateModel = function (dateText) {
        scope.$apply(function () {
          ngModelCtrl.$setViewValue(dateText);
        });
      };
      var options = {
        dateFormat: "dd/mm/yy",
        onSelect: function (dateText) {
          updateModel(dateText);
        }
      };
      elem.datepicker(options);
    }
  }
});

答案 1 :(得分:1)

只需将corsFilter块移动到Authenticator块上方,如下所示:

public function behaviors()
    {
        return [
            'corsFilter' => [
                'class' => \yii\filters\Cors::className(),
            ],
            'authenticator' => [
                'class' => HttpBearerAuth::className(),
            ],
            'contentNegotiator' => [
                'class' => ContentNegotiator::className(),
                'formats' => [
                    'application/json' => Response::FORMAT_JSON,
                ],
            ],

        ];
    }