tutorial component auth authentication login cakephp-2.1

component - Authentication de CakePHP 2.x con dos inicios de sesión separados



cakephp auth (2)

En mayo, publiqué esta pregunta . Intento hacer lo mismo otra vez en una aplicación diferente, pero no he encontrado una solución a este problema. Tengo más información y mejor código, así que espero que ustedes puedan ayudarme a resolver esto.

Caso de uso: la oficina del doctor tiene un sitio web con usuarios administradores. Los usuarios inician sesión con éxito con Auth de CakePHP a través del modelo de User y UsersController .

Los médicos tienen médicos referentes con perfiles y acciones completamente diferentes. Los médicos necesitan iniciar sesión a través de example.com/physicians/login . Sin embargo, este inicio de sesión está fallando con esto

authError => ''You are not authorized to access that location.''

Aquí está mi código en AppController :

class AppController extends Controller { public $helpers = array(''Form'', ''Html'', ''Time'', ''Session'', ''Js'' => array(''Jquery'')); public $components = array( ''Session'', ''Auth'' => array( ''autoRedirect'' => false, ''authorize'' => ''Controller'' ) ); public function beforeFilter() { $this->Auth->allow(''index'', ''view'', ''edit'', ''display'', ''featured'', ''events'', ''contact'', ''signup'', ''search'', ''view_category'', ''view_archive'', ''addComment'', ''schedule'', ''login''); }

}

Y aquí está mi UsersController que está funcionando:

class UsersController extends AppController { public $components = array( ''Auth'' => array( ''authenticate'' => array( ''Form'' => array( ''userModel'' => ''User'', ''fields'' => array( ''username'' => ''username'', ''password'' => ''password'' ) ) ), ''loginRedirect'' => array(''controller'' => ''users'', ''action'' => ''admin''), ''logoutRedirect'' => array(''controller'' => ''pages'', ''action'' => ''index''), ''loginAction'' => array(''controller'' => ''users'', ''action'' => ''login''), ''sessionKey'' => ''Admin'' ) ); public function beforeFilter() { parent::beforeFilter(); $this->Auth->allow(''add'', ''login'', ''logout''); } function isAuthorized() { return true; } public function login() { if ($this->request->is(''post'')) { if ($this->Auth->login()) { $this->redirect($this->Auth->redirect()); } else { $this->Session->setFlash(__(''Invalid username or password, try again'')); } } } public function logout() { $this->Session->destroy(); $this->redirect($this->Auth->logout()); }

Aquí está mi código de PhysiciansController que NO está funcionando:

class PhysiciansController extends AppController { public $components = array( ''Auth'' => array( ''authenticate'' => array( ''Form'' => array( ''userModel'' => ''Physician'', ''fields'' => array( ''username'' => ''username'', ''password'' => ''password'' ) ) ), ''loginRedirect'' => array(''controller'' => ''physicians'', ''action'' => ''dashboard''), ''logoutRedirect'' => array(''controller'' => ''pages'', ''action'' => ''index''), ''loginAction'' => array(''controller'' => ''physicians'', ''action'' => ''login''), ''sessionKey'' => ''Physician'' ) ); public function beforeFilter() { parent::beforeFilter(); $this->Auth->authorize = array( ''Actions'' => array( ''userModel'' => ''Physician'', ''actionPath'' => ''physicians'' ) ); $this->Auth->allow(''login'', ''logout''); // $this->Session->write(''Auth.redirect'',''/physicians/index''); } function isAuthorized() { return true; } public function login() { if ($this->request->is(''post'')) { if ($this->Auth->login()) { $this->redirect(array(''controller'' => ''physicians'', ''action'' => ''dashboard'')); } else { $this->Session->read(); debug($this->Auth); $this->Session->setFlash(__(''Invalid username or password, try again'')); } } } public function logout() { $this->Session->destroy(); $this->redirect($this->Auth->logout()); }

Realmente no quiero volver a empezar y cambiar a ACL. No estoy seguro de que sea necesario para solo dos inicios de sesión. ¡La ayuda sería muy apreciada!

EDITAR: La respuesta de Joshua a continuación es increíble y muy útil. Lo implementé, pero sigo recibiendo un error no autorizado cuando intento iniciar sesión como Médico a través de / phys / physican / login (prefijo / controlador / acción). La configuración del administrador funciona de maravilla. Aquí está el código de depuración cuando intento iniciar sesión:

object(AuthComponent) { components => array( (int) 0 => ''Session'', (int) 1 => ''RequestHandler'' ) authenticate => array( ''Form'' => array( ''userModel'' => ''Physician'' ) ) authorize => false ajaxLogin => null flash => array( ''element'' => ''default'', ''key'' => ''auth'', ''params'' => array() ) loginAction => array( ''controller'' => ''physicians'', ''action'' => ''phys_login'' ) loginRedirect => null logoutRedirect => ''/'' authError => ''You are not authorized to access that location.'' allowedActions => array() request => object(CakeRequest) { params => array( ''prefix'' => ''*****'', ''plugin'' => null, ''controller'' => ''physicians'', ''action'' => ''phys_login'', ''named'' => array(), ''pass'' => array(), ''phys'' => true, ''_Token'' => array( ''key'' => ''ad1ea69c3b2c7b9e833bbda03ef18b04079b23c3'', ''unlockedFields'' => array() ), ''isAjax'' => false ) data => array( ''Physician'' => array( ''password'' => ''*****'', ''username'' => ''deewilcox'' ) ) query => array() url => ''phys/physicians/login'' base => '''' webroot => ''/'' here => ''/phys/physicians/login'' } response => object(CakeResponse) { } settings => array()

}


En lugar de

$this->Session->write(''Auth.redirect'',''/physicians/index'');

Deberías usar

setcookie("keys", value);


OK, tengo una manera de hacerlo. ¿Conoces el enrutamiento de prefijos? De lo contrario, lea mi respuesta aquí: colocación de las funciones de administración de CakePHP / MVC Esa respuesta describe cómo configurar un prefijo de enrutamiento único (''admin''). Pero puedes tener cualquier número, así como esto:

Configure::write(''Routing.prefixes'', array(''admin'',''phys'',''member'',''user'')); // now we have admin, phys, member and user prefix routing enabled.

Lo que puede hacer es que todos los métodos del médico utilicen el enrutamiento de prefijo ''admin'', y todos los métodos de los médicos usan el enrutamiento de prefijo ''phys''.

Entonces el siguiente es un código que he pirateado bastante rápido, por lo que podría no ser perfecto, pero debería mostrar el concepto. Aquí está en pseudocódigo para el método de filtro anterior de su controlador de aplicación:

if (USER IS TRYING TO ACCESS AN ADMIN PREFIXED METHOD) { Then use the users table for auth stuff } else if (USER IS TRYING TO ACCESS A PHYS PREFIXED METHOD) { Then use the physicians table for auth stuff } else { It''s neither an admin method, not a physicians method. So just always allow access. Or always deny access - depending on your site }

Aquí está mi código de controlador de la aplicación:

App::uses(''Controller'', ''Controller''); class AppController extends Controller { public $components = array(''Security'',''Cookie'',''Session'',''Auth'',''RequestHandler''); public $helpers = array(''Cache'',''Html'',''Session'',''Form''); function beforeFilter() { if ($this->request->prefix == ''admin'') { $this->layout = ''admin''; // Specify which controller/action handles logging in: AuthComponent::$sessionKey = ''Auth.Admin''; // solution from https://.com/questions/10538159/cakephp-auth-component-with-two-models-session $this->Auth->loginAction = array(''controller''=>''administrators'',''action''=>''login''); $this->Auth->loginRedirect = array(''controller''=>''some_other_controller'',''action''=>''index''); $this->Auth->logoutRedirect = array(''controller''=>''administrators'',''action''=>''login''); $this->Auth->authenticate = array( ''Form'' => array( ''userModel'' => ''User'', ) ); $this->Auth->allow(''login''); } else if ($this->request->prefix == ''phys'') { // Specify which controller/action handles logging in: AuthComponent::$sessionKey = ''Auth.Phys''; // solution from https://.com/questions/10538159/cakephp-auth-component-with-two-models-session $this->Auth->loginAction = array(''controller''=>''users'',''action''=>''login''); $this->Auth->logoutRedirect = ''/''; $this->Auth->authenticate = array( ''Form'' => array( ''userModel'' => ''Physician'', ) ); } else { // If we get here, it is neither a ''phys'' prefixed method, not an ''admin'' prefixed method. // So, just allow access to everyone - or, alternatively, you could deny access - $this->Auth->deny(); $this->Auth->allow(); } } public function isAuthorized($user){ // You can have various extra checks in here, if needed. // We''ll just return true though. I''m pretty certain this method has to exist, even if it just returns true. return true; } }

Tenga en cuenta las líneas:

AuthComponent::$sessionKey = ''Auth.Admin''; // solution from https://.com/questions/10538159/cakephp-auth-component-with-two-models-session

y

AuthComponent::$sessionKey = ''Auth.Phys''; // solution from https://.com/questions/10538159/cakephp-auth-component-with-two-models-session

Lo que hace es permitir que una persona inicie sesión como médico y como administrador, en el único navegador, sin interferir con la sesión del otro. Es posible que no lo necesite en el sitio en vivo, pero sin duda es útil durante la prueba.

Ahora, en sus respectivos controladores, necesitará métodos simples de inicio de sesión / cierre de sesión, con el prefijo apropiado.

Por lo tanto, para el prefijo de administrador, en su controlador de usuario:

public function admin_login() { if ($this->request->is(''post'')) { if ($this->Auth->login()) { return $this->redirect($this->Auth->redirect()); } else { $this->Session->setFlash(__(''Username or password is incorrect''), ''default'', array(), ''auth''); } } } public function admin_logout() { $this->Session->setFlash(''Successfully Logged Out''); $this->redirect($this->Auth->logout()); }

Y en su controlador de médicos:

public function phys_login() { if ($this->request->is(''post'')) { if ($this->Auth->login()) { return $this->redirect($this->Auth->redirect()); } else { $this->Session->setFlash(__(''Username or password is incorrect''), ''default'', array(), ''auth''); } } } public function phys_logout() { $this->Session->setFlash(''Successfully Logged Out''); $this->redirect($this->Auth->logout()); }

Como dije, ese código pirateé bastante rápido, así que podría no funcionar al pie de la letra, pero debería mostrar el concepto. Hazme saber si tienes alguna pregunta.