В настоящее время я разрабатываю restful / stateless api в cakephp, который использует токены (на данный момент) и должен использовать в будущем маркеры (например, предлагаемые здесь от g-shearer). Моя текущая реализация работает, но я действительно обеспокоен тем, что я реализовал все правильно (компоненты auth, особенно настраиваемые компоненты auth, кажутся мне очень запутанными)
PS: Я использую текущую версию cakephp (2.5.1).
1: Я создал файл TokenAuthenticate.php в Controller / Component / Auth:
<?php App::uses('BaseAuthenticate', 'Controller/Component/Auth'); class TokenAuthenticate extends BaseAuthenticate { public function authenticate(CakeRequest $request, CakeResponse $response) { } public function getUser(CakeRequest $request) { //set values from request headers $publictoken = $request->header('Security-Public-Token'); $accesstoken = $request->header('Security-Access-Token'); $timestamp = $request->header('Security-Timestamp'); // check if required header fields are set if (empty($publictoken) || empty($accesstoken) || empty($timestamp)) { return false; } // init required token model $Token = ClassRegistry::init('Token'); //check if token pair exists if ($dbtoken = $Token->findByPublic($publictoken)) { if ($accesstoken == md5($dbtoken['Token']['private'] . $timestamp)) { //valid token - return user $User = ClassRegistry::init('User'); $dbuser = $User->findById($dbtoken['Token']['user_id'])['User']; return $dbuser; } else { //invalid token return false; } } else { //invalid token pair return false; } } public function unauthenticated(CakeRequest $request, CakeResponse $response) { return true; } } ?>
то я добавил к контроллеру следующее:
class UsersController extends AppController { public $uses = array('User', 'Token'); public $components = array('Auth' => array('authenticate' => array('Token'))); public function beforeFilter() { parent::beforeFilter(); AuthComponent::$sessionKey = false; $this->Auth->autoRedirect = false; $this->Auth->allow('login', 'register'); }
в моих действиях я проверяю статус следующим образом:
if (!$this->Auth->loggedIn()) { $this->set(array('error' => 'INVALID_AUTHENTIFICATION')); $this->render('view'); }
Поэтому я могу установить пользовательскую ошибку и вывести ее, не перенаправляясь на действие входа (обратите внимание на неаутентифицированную функцию в моем файле tokenauthentication, который возвращает true, поэтому cakephp не перенаправляет вас)
Я думаю, что процесс регистрации должен произойти в функции аутентификации моего файла TokenAuthenticate, а не в действии входа моего контроллера, или я ошибаюсь? Каков правильный способ достижения этой цели?
PS: Как можно было бы автоматически добавить новую пару токенов (для каждого аутентифицированного вывода) с помощью cakephp, чтобы токены были «катящимися»?
Весь вывод api кодируется json, если это имеет значение
также cakephp по-прежнему задает cookie иногда, даже если я отключил это (AuthComponent :: $ sessionKey = false;). Как остановить это?
EDIT: Таким образом, я добавил функцию beforeRender () в свой usercontroller, и теперь маркеры катятся (Y)
//renew tokens public function beforeRender() { //only add tokens if logged in if ($this->Auth->loggedIn()) { //find old token $oldToken = $this->Token->findByUser_id($this->Auth->user('id')); //delete old token $this->Token->delete($oldToken['Token']['id']); //create new token pair $this->Token->create(); $this->Token->save(array( 'user_id' => $this->Auth->user('id'), 'public' => Security::hash(substr(str_shuffle('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$') , 0 , 15 )), 'private' => Security::hash(substr(str_shuffle('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$') , 0 , 15 )) )); //set it for the view $this->set(array('token' => $this->Token->read())); } }
Это правильный способ реализовать что-то вроде этого? Я всегда хочу делать все правильно и «отлично», поэтому любой критик приветствуется 🙂