Yii2 Rest - 自定义动作和选项方法 [英] Yii2 Rest - Custom action and OPTIONS method

查看:52
本文介绍了Yii2 Rest - 自定义动作和选项方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 UsersController 类中执行以下操作/login"路由操作时遇到问题

I'm having trouble with the following action "/login" route action in my UsersController class

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 路由以检查它是否被允许或不要用 POST 调用/login ..

The situation is that I'm using POST method to perform login, and I'm calling this route from a different domain, so the frontend library first try to call /login route with OPTIONS method to check if it is allowed or not to call /login with POST..

问题是 yii2 rest ActiveController 的内置功能仅适用于/users 和/users/{id}

The problem is that the built in functionality of yii2 rest ActiveController is only for /users and /users/{id}

如果我通过动作动词过滤器手动添加此/login 路由以在 POST 和 OPTIONS 中可用,那么 yii 正在尝试使用 OPTIONS 请求实际调用登录动作.我的意思是,它正在尝试执行登录.当然不能,因为它没有发送电子邮件和密码字段,但我可以在日志文件中看到错误.

If I manually add this /login route to be available in both POST and OPTIONS through actions verbFilter, then yii Is trying to actually call the login action with the OPTIONS request. I mean, it is trying to perform login. Of course it can't, because it is not sending email and passwords fields, but I can see an error in the log file.

所以,我的问题是......有没有办法正确配置这个自定义"路由操作并使OPTIONS透明地执行?因为我期望在使用 OPTIONS 调用它时不会执行登录操作,而是直接返回 OPTIONS 允许的方法标头.

So, my question is... Is there any way to configure correctly this "custom" routes actions and make OPTIONS performs transparently? Because I'm expecting that login action not get executed when calling it with OPTIONS, but instead to return directly the OPTIONS allowed methods headers.

更新信息:添加了 URL 管理器规则

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

推荐答案

默认情况下 yii\rest\UrlRule 类会将这些模式应用于任何端点:

By default the yii\rest\UrlRule class will apply those patterns to any endpoint :

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

这意味着,如果您的 loginAction 写在一个扩展 ActiveControlleryii\rest\OptionsAction>.

Which means that any request holding OPTIONS verbs will be redirected to yii\rest\OptionsAction if your loginAction is written inside a class extending ActiveController.

我的建议是通过保留唯一使用的动词来覆盖 patterns,因为您的 login 操作不需要任何其他 CRUD 操作.这应该适用于您的情况:

What I suggest is to override patterns by leaving the only used verbs as your login action doesn't need any of the other CRUD actions. this should work with your case :

'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 动词如果未通过身份验证将被拒绝.

NOTE: the solution by @CreatoR is also a requirement here and exactly as he did it without defining keys. otherwise OPTIONS verbs will be rejected if not authenticated.

如果你的 login 动作是在一个直接扩展 yii\rest\Controller 的类下定义的,而不是通过 yii\rest\ActiveController>(这应该适用于身份验证操作,因为这里不需要 CRUD)那么相同的规则配置应该可以正常工作,但您需要手动将 actionOptions 添加到您的代码:

In case if your login action is defined under a class extending yii\rest\Controller directly instead of passing through yii\rest\ActiveController (which should be appropriate for authentication actions as there is no CRUD needed here) then the same rules configs should work fine but you'll need to manually add the actionOptions to your code :

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

这篇关于Yii2 Rest - 自定义动作和选项方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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