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

Dub*_*bby 4 php rest cors yii2

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

网址管理员:

['class' => 'yii\rest\UrlRule', 'controller' => 'api/v1/user', 'pluralize' => false],
Run Code Online (Sandbox Code Playgroud)

控制器行为:

public function behaviors()
{
    return ArrayHelper::merge([
            'corsFilter' => [
                'class' => Cors::className(),
            ],
            [
                'class' => HttpBearerAuth::className(),
                'except' => ['options',
                             'login',
                ],
            ],
        ], parent::behaviors()
    );
}
Run Code Online (Sandbox Code Playgroud)

如上所述,CRUD的操作很好,但是自定义操作http://domain.com/user/test会响应401 Unauthorised响应.

是不是可以让CORS和auth在自定义操作上一起工作?

编辑:我应该补充说,问题(401)仅在浏览器发出OPTIONS请求时发生.正常请求(curl,Postman)不受影响.RESTful,Cors,Auth组合似乎会出现这个问题.

Sal*_*ani 9

试试这个:

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;
}
Run Code Online (Sandbox Code Playgroud)

它将取消设置父控制器authenticator实现的默认值,以确保首先处理该默认值.然后我们强制在实现您自己的凭据之前允许凭据.corscorsauthenticator


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

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

实现的默认CRUD操作ActiveController正在使用这些默认模式:

'PUT,PATCH {id}' => 'update',
'DELETE {id}' => 'delete',
'GET,HEAD {id}' => 'view',
'POST' => 'create',
'GET,HEAD' => 'index',
'{id}' => 'options',
'' => 'options',
Run Code Online (Sandbox Code Playgroud)

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

[
    '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',
    ]
],
Run Code Online (Sandbox Code Playgroud)

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


Options默认情况下,该操作已实施ActiveController.它的代码可以在这里看到.如果你正在扩展一个不同的控制器,ActiveController可能\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;
}
Run Code Online (Sandbox Code Playgroud)