Yii2 CORS与Auth不工作的非CRUD操作 [英] Yii2 CORS with Auth not working for non CRUD actions

查看:1752
本文介绍了Yii2 CORS与Auth不工作的非CRUD操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



网址管理员:

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

控制器行为:

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

如上所述,CRUD的操作很好,但是自定义操作c $ c> http://domain.com/user/test 将以 401未授权回应回应。



是否不可能获得CORS和auth一起工作的自定义操作?



编辑:我应该补充说,问题只有当浏览器发出 OPTIONS 请求时才会发生。正常请求(curl,Postman)不受影响。

解决方案

尝试:

  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;
}

它会取消设置 c> authenticationator 由实施父控制器,以确保 cors 被首先处理。然后,我们在实施您自己的认证程序之前,强制 cors 允许凭据。




另一件可能会导致未授权错误的原因是未找到或错误选项响应作为浏览器请求它首先获得允许的动词列表。



一般规则是当您要求您的浏览器执行一个明智的动词,例如PUT,DELETE或POST时,您可以在浏览器的网络标签中检查该列表。到任何网址,它可能首先向该相同的网址发送OPTIONS请求(检查

ActiveController 正在使用这些默认模式

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

因此,在 urlManager ['rules '] 确保不覆盖它们中的最后两个,如果您使用自定义模式,请始终记住包括其等效的选项动词示例:

  [
'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',
//选项VERBS
'OPTIONS login'=> 'options',
'OPTIONS signup'=> 'options',
'OPTIONS req-reset-pass'=> 'options',
'OPTIONS reset-pass'=> 'options',
]
],

extraPatterns 中的模式。






选项操作默认在 ActiveController 。其代码可以在此处查看。
如果你扩展一个不同的控制器比 ActiveController 像可能 \yii\rest\Controller

  public function actions()
{
$ actions = parent :: actions();
$ actions ['options'] = [
'class'=> 'yii\rest \OptionsAction',
//可选:
'collectionOptions'=> ['GET','POST','HEAD','OPTIONS'],
'resourceOptions'=> ['GET','PUT','PATCH','DELETE','HEAD','OPTIONS'],
];
return $ actions;
}


I am building an API in Yii2 and have added CORS and authentication. This works fine for all Create/Read/Update/Delete actions but not for custom actions. Has anyone experienced this before?

URL manager:

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

Controller behaviors:

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

As mentioned, actions for CRUD are fine but a custom action such as http://domain.com/user/test will respond with a 401 Unauthorised response.

Is it not possible to get CORS and auth to work together on custom actions?

Edit: I should add that the issue (401) occurs only when a browser makes the OPTIONS request. Normal requests (curl,Postman) are not affected. The issue seems to occur with the RESTful,Cors,Auth combination.

解决方案

try this:

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;
}

It will unset the default authenticator implemented by the parent controller to be sure that cors is treated first. Then we force cors to allow credentials before implementing your own authenticator.


The other thing that may raise that Unauthorized error is a not-found or wrong Options response as a browser request it first to get a list of allowed verbs. You may check that list in its headers response within your browser's network tab.

The general rule is when you ask your browser to perform a sensible verb like PUT, DELETE or POST to any url it may first send an OPTIONS request to that same url (check this) to check if that verb is allowed before sending the real request. So Yii should be configured to respond to all those OPTIONS verbs by performing the correct redirections.

The default CRUD actions implemented by ActiveController are using those default patterns:

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

So whatever configurations you did implement in urlManager['rules'] be sure to not override the last 2 of them and if you are using custom patterns always remember to include its equivalent options verbs like in this example:

[
    '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',
    ]
],

The same applies when adding custom patterns within extraPatterns.


The Options action is implemented by default in ActiveController. it's code can be seen here. In case you are extending a different controller than ActiveController like maybe \yii\rest\Controller be sure to manually include it:

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;
}

这篇关于Yii2 CORS与Auth不工作的非CRUD操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆