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

网址管理员:

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

Controller 行为:
public function behaviors()
{
    return ArrayHelper::merge([
            'corsFilter' => [
                'class' => Cors::className(),
            ],
            [
                'class' => HttpBearerAuth::className(),
                'except' => ['options',
                             'login',
                ],
            ],
        ], parent::behaviors()
    );
}

如前所述,用于CRUD的操作很好,但是诸如http://domain.com/user/test之类的自定义操作将以401 Unauthorised响应进行响应。

是否无法让CORS和auth一起执行自定义操作?

编辑:我应该补充说,仅当浏览器发出OPTIONS请求时才会出现问题(401)。普通请求(curl,Postman)不受影响。 RESTful,Cors,Auth组合似乎发生了此问题。

最佳答案

试试这个:

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响应,因为浏览器首先请求它获得允许的动词列表。您可以在浏览器的“网络”标签中的标题响应中检查该列表。

一般规则是,当您要求浏览器对任何 url 执行明智的动词(如PUT,DELETE或POST)时,它可能会先向同一 url (检查this)发送一个OPTIONS请求,以检查该动词是否被允许发送真实的请求。因此,应将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']中实现了哪种配置,请确保不要覆盖它们的后2个,并且如果您使用的是自定义模式,请务必记住包括其等效的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',
    ]
],

extraPatterns 中添加自定义模式时,也是如此。
Options操作默认在ActiveController中实现。可以看到它的代码here
如果要扩展与ActiveController不同的 Controller (例如\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;
}

关于php - 带有Auth的Yii2 CORS无法用于非CRUD操作,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36274089/

10-11 20:02
查看更多