繁体   English   中英

CakePHP 3 REST API身份验证,同时仍使用现有控制器

[英]CakePHP 3 REST API authentication while still using the existing controllers

我在CakePHP 3中为移动设备实现REST API身份验证时遇到了问题。

阅读认证官方CakePHP 3文档:

http://book.cakephp.org/3.0/en/controllers/components/authentication.html#id1

它说我可以使用无状态基本身份验证而不是表单身份验证。 但是,我也在其中一个论坛中读到,您不能同时使用基本身份验证和表单身份验证。

我还研究了使用REST API的前缀路由。

http://www.bravo-kernel.com/2015/04/how-to-prefix-route-a-cakephp-3-rest-api/

通过这样做,我现在可以对前缀路由执行基本身份验证,对非前缀路由执行表单身份验证。 但是,这需要在其前缀命名空间中定义控制器,这违反了CakePHP保持代码DRY的概念; 因为我的控制器已经包含适用于网络和移动设备的逻辑。

如果我只是使用表单身份验证,我可以从我的手机创建一个POST请求到Web系统,但响应将是HTML格式。 解析整个HTML格式不是一个好方法。

我被困住了,不知道该怎么办。 我整个下午一直在研究,但仍未能找到解决方案。

我想要的是能够通过我的移动应用程序进行身份验证,同时仍然使用相同的控制器。

编辑:解决方法

class AppController extends Controller
{
    public function initialize()
    {
        parent::initialize();
        $this->loadComponent('Auth', [
            'authorize' => 'Controller',
            'authenticate' => [
                'Form' => [
                    'fields' => [
                        'username' => 'username',
                        'password' => 'password'
                    ]
                ]
            ],
            'loginAction' => ['controller' => 'Users', 'action' => 'login'],
            'unauthorizedRedirect' => $this->referer()
        ]);
    }

    public function beforeFilter(Event $event)
    {
        if($this->request->params['_ext'] === 'json')
        {
            $this->Auth->config('authenticate', ['Basic' => ['userModel' => 'Users']]);
            $this->Auth->config('storage', 'Memory');
            $this->Auth->config('unauthorizedRedirect', false);
        }
        return parent::beforeFilter($event);
    }
}

通过有条件地将基本身份验证添加到身份验证配置来管理以使其工作。

然而,这不是一个完美的解决方案,因为它肯定有陷阱。

这只能在以下假设下工作:

  1. 参考这篇文章:CakePHP将根据身份验证方案的顺序执行优先级。 由于Form Auth在Basic Auth之前,如果Form Auth成功,Basic Auth将不会执行。

    CakePHP 2.1 - 作为具有身份验证的Web应用程序和REST服务

  2. 通常,Web用户不会访问具有json文件扩展名的URL,因此将使用表单身份验证将用户重定向到用户登录页面。

  3. 通过表单身份验证对用户进行身份验证后,即使用户使用AJAX间接访问以.json结尾的URL,也不会弹出基本身份验证。

有没有更好的方法?

您可以通过使用basic authentication来实现此目的。对于Web,您必须使用form authentication而对于REST API您必须使用basic authentication并且您可以一次使用两者。我已经实现了它,下面是工作示例。

   public function initialize() {
        parent::initialize();
        $this->loadComponent('RequestHandler');
        $this->loadComponent('Flash');
        $url = $this->request->url;
        $ext = $this->request->params['_ext'];
        if ((isset($ext) && $ext == 'json') && (!($this->request->is('ajax')) && ($url != 'users/loginapi.json')) ) {    
            $this->loadComponent('Auth', [
                'authenticate' => [
                    'Basic' => [
                        'fields' => ['username' => 'email', 'password' => 'api_key'],
                        'userModel' => 'Users',
                        'scope' => ['status' => 'A']
                    ],
                ],
                'storage' => 'Memory',
                'unauthorizedRedirect' => false
            ]);
        } else {
            $this->loadComponent('Auth', [
                'authenticate' => [
                    'Form' => [
                        'fields' => ['username' => 'email_or_mobile', 'password' => 'password'],
                        'userModel' => 'Users',
                        'scope' => ['status' => 'A'],
                        'finder' => 'auth'
                    ]
                ],
                'storage' => 'Session',
                //'unauthorizedRedirect' => false,
                'loginRedirect' => [
                    'controller' => 'Users',
                    'action' => 'index'
                ],
                'logoutRedirect' => [
                    'controller' => 'Users',
                    'action' => 'login'
                ],
                'authError' => false
            ]);
        }
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM