我在执行以下操作时出现问题" / login"我的UsersController类中的路由操作
public function actionLogin(){
$data = Yii::$app->getRequest()->getBodyParams();
$model = new Usuario();
//Validamos que se hayan recibido los campos
if(empty($data['email']) || empty($data['password'])){
throw new \yii\web\BadRequestHttpException("Debe ingresar email y password");
}
//Validamos usuario y contraseña
$usuario = $model->findByUsername($data['email']);
if(empty($usuario) || !$usuario->validatePassword($data['password'])){
throw new \yii\web\UnauthorizedHttpException("Usuario y/o contraseña incorrectos");
}
return $usuario;
}
情况是我使用POST方法执行登录,并且我从不同的域调用此路由,因此前端库首先尝试使用OPTIONS方法调用/ login route来检查是否允许或不允许使用POST调用/登录..
问题是yii2 rest ActiveController的内置功能仅适用于/ users和/ users / {id}
如果我通过动作verbFilter手动添加此/登录路由以在POST和OPTIONS中都可用,则yii尝试使用OPTIONS请求实际调用登录操作。我的意思是,它正在尝试登录。当然它不能,因为它不发送电子邮件和密码字段,但我可以在日志文件中看到错误。
所以,我的问题是......有没有办法正确配置这个" custom"路由操作并使OPTIONS透明地执行?因为我希望在使用OPTIONS调用它时不会执行登录操作,而是直接返回OPTIONS允许的方法标题。
更新信息:添加了网址管理员规则
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => true,
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'controller' => ['v1/users'],
'pluralize' => false,
'tokens' => [
'{id}' => '<id:\\w+>'
]
],
//Rutas usuario
'v1/login' => '/v1/users/login'
],
],
答案 0 :(得分:7)
默认情况下,yii\rest\UrlRule
类会将这些模式应用于任何端点:
'patterns' => [
'PUT,PATCH {id}' => 'update',
'DELETE {id}' => 'delete',
'GET,HEAD {id}' => 'view',
'POST' => 'create',
'GET,HEAD' => 'index',
'{id}' => 'options',
'' => 'options',
]
这意味着如果您的yii\rest\OptionsAction
写在扩展 ActiveController 的类中,则任何包含OPTIONS谓词的请求都将被重定向到loginAction
。
我建议通过留下唯一使用的动词来覆盖patterns
,因为您的登录操作不需要任何其他CRUD操作。这适用于您的情况:
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'controller' => ['v1/users'],
'pluralize' => false,
'tokens' => [
'{id}' => '<id:\\w+>'
]
],
[
'class' => 'yii\rest\UrlRule',
'controller' => ['v1/login' => '/v1/users/login'],
'patterns' => [
'POST' => 'login',
'' => 'options',
]
]
],
注意:@CreatoR的解决方案在这里也是一个要求,就像他没有定义键一样。否则OPTIONS谓词如果未经过身份验证将被拒绝。
如果登录操作是在直接扩展yii\rest\Controller
的类下定义的,而不是通过yii\rest\ActiveController
(这应该适用于身份验证操作,因为没有CRUD这里需要)然后相同的规则配置应该可以正常工作,但您需要手动将 actionOptions 添加到您的代码中:
// grabbed from yii\rest\OptionsAction with a little work around
private $_verbs = ['POST','OPTIONS'];
public function actionOptions ()
{
if (Yii::$app->getRequest()->getMethod() !== 'OPTIONS') {
Yii::$app->getResponse()->setStatusCode(405);
}
$options = $this->_verbs;
Yii::$app->getResponse()->getHeaders()->set('Allow', implode(', ', $options));
}
答案 1 :(得分:4)
我有同样的问题。
这就是我修复它的方法:
我在规则中添加了extraPatterns
参数,如下所示:
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'pluralize' => false,
'controller' => [
'athlete',
'admin',
'address',
'program'
],
'extraPatterns' => [
'OPTIONS <action:\w+>' => 'options'
]
]
],
],
这样,我将在任何这些控制器中为每个自定义操作调用options
操作。
答案 2 :(得分:3)
我通过扩展Cors过滤器类来解决问题:
use Yii;
use yii\filters\Cors;
class CorsCustom 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();
unset($behaviors['authenticator']);
$behaviors['corsFilter'] = [
'class' => CorsCustom::className(),
];
$behaviors['authenticator'] = [
'class' => HttpBearerAuth::className(),
'optional' => ['login']
];
return $behaviors;
}
答案 3 :(得分:0)
您需要在控制器的Cors
方法中附加behaviours()
过滤器(请参阅in official guide)以下条件:
Cors
过滤器
option
过滤器AccessControl
进行操作
醇>
在您的情况下,UsersController
可能有behaviors()
方法:
public function behaviors()
{
return ArrayHelper::merge(
[
'cors' => [
'class' => Cors::className(),
],
],
parent::behaviors(),
[
'access' => [
'class' => AccessControl::className(),
'rules' => [
['allow' => true, 'actions' => ['options']],
]
],
]
);
}
答案 4 :(得分:0)
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'controller' => ['v1/users'],
'pluralize' => false,
'tokens' => [
'{id}' => '<id:\\w+>'
]
],
[
'class' => 'yii\rest\UrlRule',
'controller' => ['v1/login' => '/v1/users/login'],
'patterns' => [
'POST' => 'login',
'OPTIONS' => 'options',
]
]
],