Authentication 具有两个独立登录名的CakePHP 2.x Auth
早在五月份,我就发帖了。我正试图在另一个应用程序上再次做同样的事情,但我还没有找到解决这个问题的方法。我有更多的信息和更好的代码,所以我希望你们能帮我解决这个问题 用例: 医生办公室有一个管理用户网站。用户通过Authentication 具有两个独立登录名的CakePHP 2.x Auth,authentication,login,cakephp-2.1,Authentication,Login,Cakephp 2.1,早在五月份,我就发帖了。我正试图在另一个应用程序上再次做同样的事情,但我还没有找到解决这个问题的方法。我有更多的信息和更好的代码,所以我希望你们能帮我解决这个问题 用例: 医生办公室有一个管理用户网站。用户通过Usermodel和userscocontroller使用CakePHP的Auth成功登录 医生有完全不同的概况和行动的转诊医生。医生需要通过example.com/medicages/login登录。但是,此登录失败,原因是 authError=>“您无权访问该位置。” 这是我在AppC
User
model和userscocontroller
使用CakePHP的Auth成功登录
医生有完全不同的概况和行动的转诊医生。医生需要通过example.com/medicages/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');
}
}
这是我的userscoontroller
,它正在工作:
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());
}
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());
}
这是我的PhysiciansController
代码,它不起作用:
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());
}
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());
}
我真的不想重新开始并切换到ACL——我不确定仅仅两次登录是否需要ACL。非常感谢您的帮助
编辑:约书亚下面的回答非常棒,非常有用。我实现了它,但当我尝试通过/phys/physican/login(前缀/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()
}好的,我有办法。你知道前缀路由吗?如果没有,请阅读我的答案:该答案描述了如何设置单个路由前缀(“admin”)。但是你可以有任何号码,就像这样:
Configure::write('Routing.prefixes', array('admin','phys','member','user'));
// now we have admin, phys, member and user prefix routing enabled.
你可以做的是让所有医生的方法使用“admin”前缀路由,所有医生的方法使用“phys”前缀路由
下面的代码是我很快拼凑起来的,所以它可能并不完美,但它应该显示出这个概念。这里是应用程序控制器的before filter方法的伪代码:
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
}
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'), 'default', array(), 'auth');
}
}
}
public function phys_logout() {
$this->Session->setFlash('Successfully Logged Out');
$this->redirect($this->Auth->logout());
}
以下是我的应用程序控制器代码:
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://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
及
这样做的目的是允许一个人在一个浏览器中以医生和管理员的身份登录,而不会干扰彼此的会话。您可能不需要在实时站点中使用它,但它在测试时确实非常方便
现在,在各自的控制器中,您需要具有适当前缀的直接登录/注销方法
因此,对于管理员前缀,在用户控制器中:
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
}
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'), 'default', array(), 'auth');
}
}
}
public function phys_logout() {
$this->Session->setFlash('Successfully Logged Out');
$this->redirect($this->Auth->logout());
}
在您的控制器中:
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
}
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'), 'default', array(), 'auth');
}
}
}
public function phys_logout() {
$this->Session->setFlash('Successfully Logged Out');
$this->redirect($this->Auth->logout());
}
正如我所说,我很快就把所有代码拼凑在一起,所以它可能无法一字不差地工作,但它应该显示出这个概念。如果您有任何问题,请告诉我。而不是
$this->Session->write('Auth.redirect','/physicians/index');
你应该使用
setcookie("keys", value);
非常感谢,你太棒了。我今天实现了,在管理前缀和用户控制器方面没有问题。然而,内科医生主管仍然给我同样的“您未经授权”错误。因此,几乎没有任何变化。如果有帮助的话,我将发布上面的调试代码。那么您是获得“无效用户名或密码,请重试”,还是根本没有获得,只是获得“您无权访问该位置”?也就是说,你的“如果($this->Auth->login()){”通过了,那么你只会在登录后重定向上遇到问题吗?或者那行失败了吗?我得到了“你没有被授权”错误。如果我通过了
($this->request->data)
,它会工作。我用$this->Auth->login($this->request->data)测试了一个无效的用户名和密码;
,登录失败(应该如此)如果用户名或密码错误。我已经成功地使用sessionKey为用户和企业分别登录了两次,并且我可以在同一时间使用不同的凭据在两端登录,但问题是当我从用户端注销时,它也会从企业端注销,反之亦然。你能帮我解决这个问题吗ueI不确定问题出在哪里。你应该解释一下你具体做了什么,然后把它作为一个新问题发布。