早在5月份,我发布了
this question.我想在不同的应用程序上再次做同样的事情,但是我没有找到解决这个问题的办法.我有更多的信息和更好的代码,所以我希望你们可以帮助我排除这一点.
用例:
医生办公室有一个管理用户的网站.用户通过用户模型和UsersController使用CakePHP的Auth登录成功.
医生有转诊医师完全不同的情况和行为.医生需要通过example.com/physicians/login登录.但是,此登录失败
authError => “您没有权限访问该位置.”
这是我在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'); }
}
这里是我的UsersController正在工作:
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()); }
这是我的PhysiciansController代码不工作:
class PhysiciansController extends AppController { public $components = array( 'Auth' => array( 'authenticate' => array( 'Form' => array( 'userModel' => 'Physician','loginRedirect' => array('controller' => 'physicians','action' => 'dashboard'),'loginAction' => array('controller' => 'physicians','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()); }
我真的不想重新切换到ACL – 我不知道这是两次登录的必要条件.帮助将非常感谢!
编辑:约书亚在下面的答案是真棒,超级有帮助.我实现了它,但是当我尝试通过/ phys / physican / login(prefix / controller / action)作为医师登录时,我仍然收到未经授权的错误.管理员设置很好.当我尝试登录时,这是调试代码:
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()
}
好的,我有办法做到这一点.你知道前缀路由吗?如果没有,请阅读我的答案:
CakePHP/MVC Admin functions placement该答案描述如何设置单个路由前缀(‘admin’).但是你可以有任何数字 – 就像这样:
Configure::write('Routing.prefixes',array('admin','phys','member','user')); // now we have admin,phys,member and user prefix routing enabled.
您可以做的是让所有医生的方法使用’admin’前缀路由,所有医生的方法都使用’phys’前缀路由.
所以下面是我已经很快入侵的代码,所以它可能不完美,但它应该显示这个概念.这里是您的应用控制器的过滤方法的伪代码:
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 }
这是我的应用程序控制器代码:
App::uses('Controller','Controller'); class AppController extends Controller { public $components = array('Security','Cookie','Auth','RequestHandler'); public $helpers = array('Cache','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://stackoverflow.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://stackoverflow.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; } }
注意行:
AuthComponent::$sessionKey = 'Auth.Admin'; // solution from https://stackoverflow.com/questions/10538159/cakePHP-auth-component-with-two-models-session
和
AuthComponent::$sessionKey = 'Auth.Phys'; // solution from https://stackoverflow.com/questions/10538159/cakePHP-auth-component-with-two-models-session
这样做是允许一个人作为一个医生和一个管理员在一个浏览器中登录,而不会干扰对方的会话.您可能不需要它在实时网站,但它在测试当然是方便的.
现在,在各自的控制器中,您需要使用适当的前缀直接登录/注销方法.
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()); }
并在您的医生控制器:
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'),'auth'); } } } public function phys_logout() { $this->Session->setFlash('Successfully Logged Out'); $this->redirect($this->Auth->logout()); }
就像我说的那样,我所有的代码都很快被黑客入侵,所以它可能不会逐字逐句,但它应该显示这个概念.如果您有任何问题,请告诉我们.