我正在制作角度2 / Yii2 app
当我从带有承载标题的邮递员调用自定义控制器/操作时,一切正常,但是当我使用角度2应用程序(localhost:4200)中的相同标头调用它时,我总是得到未经授权的401错误。 当我执行标准操作时,例如来自guide的示例,如:
GET /users: list all users page by page;
POST /users: create a new user;
一切正常,只有在我创建自定义操作时,才会被我未经授权。
这是跨域应用程序, angular可在web.example.com上找到, yii2 app在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',
]
答案 0 :(得分:0)
我使用此处发布的解决方案解决了我的问题:
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;
}
答案 1 :(得分:0)
看起来这是一个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'];