CakePHP Auth with two tables (models)

别来无恙 提交于 2019-12-11 14:13:30

问题


I have two tables in my database, one for admins (named Admins) and the other one for normal users, named : utilisateurs (in french). I know i have to use cakePHP's convention which says i must create a table named users, which has the fields username and password. But the problem is that i have two tables and not only one. Each one has its particular fields, so i really need them to stay separated. And even informations required to login are different depending on the user :

  • admins need their login + password

  • normal users need a specific id (in their id cards) + password

What i want to do, is create two login pages, one for admins and the other for normal user. After logging in, the user is redirected to the page he is supposed to see. But yet, if the user tries attempt a forbidden location. I want be able to stop him (beforeFilter + isAuthorized i think)

How can i make all this work ?

I'm not beginner in cakephp, i've already made an authentication system in anotehr app using Auth Component, but it was a little easier because needed only one table for users.

Your help would be much appreciated.


回答1:


Assuming the following:

  • You have 2 tables associated with model User and Admin, where:
    • User has idcard and password fields.
    • Admin has login and passowrd field.
  • The passwords are hashed using User::hasPassword and Admin::hasPassword functions.
  • You login form is created as follows:

    echo $this->Form->create(null, '') ; echo $this->Form->input('login') ; echo $this->Form->input('password') ; echo $this->Form->end(__('Submit')) ;

You can create a new Authenticate component under App/Controller/Component/Auth/MyAuthenticate.php:

<?php

App::uses('FormAuthenticate', 'Controller/Component/Auth');

class MyAuthenticate extends FormAuthenticate {

    public function authenticate(CakeRequest $request, CakeResponse $response) {

        $username = $request->data['login'] ;
        $password = $request->data['password'] ;

        App::import('Model', 'User') ;
        $userModel = new User () ;

        /* Try to authenticate as a user... */
        $user = $userModel->find('first', array(
            'conditions' => array(
                'idcard' => $username,
                'password' => User::hashPassword($password) ;
            )
        )) ;

        if ($user) {
            $user = $user['User'] ; // Get only useful info
            $user['type'] = 'user'; // Save user type
            return $user ;
        }

        /* Same thing for admin. */

        App::import('Model', 'Admin') ;
        $adminModel = new Admin () ;

        $user = $adminModel->find('first', array(
            'conditions' => array(
                'login' => $username,
                'password' => Admin::hashPassword($password) ;
            )
        )) ;

        if ($user) {
            $user = $user['Admin'] ; // Get only useful info
            $user['type'] = 'admin'; // Save user type
            return $user ;
        }

        return null ;

    }

};

You just need to be sure that that a admin cannot be authenticated as a user, and reverse.

In your AppController:

public $components = array(
    'Auth' => array(
        'authenticate' => array('My'), // The prefix in front of your component
        'loginAction' => array(/* ... */),
        'loginRedirect' => array(/* ... */),
        'logoutRedirect' => array(/* ... */),
        'authError' => "...",
        'authorize' => 'Controller'
    )
) ;

Your login action is the same that for normal tables:

public function login () {
    if ($this->request->is('post')) {
        if ($this->Auth->login()) {
            $this->redirect($this->Auth->redirect());
        } 
        else {
            $this->request->data['password'] = "" ;
            $this->Session->setFlash('Invalid login/id or password.');
        }
    }
}

Then, in beforeFilter or isAuthorized you can check $this->Auth->user('type');. For example, in AppController:

public function isAuthorized () {
    /* Assuming you keep CakePHP convention where action starting with admin_ set admin params. */
    if(isset($this->params['admin'])) {
        return $this->Auth->user('type') == 'admin' ;
    }
    return true ;
}

Or if you want to disable access for non admin users to all action in AdminController, use beforeFilter:

class AdminController extends AppController {

    public function beforeFilter () {
        if (!$this->Auth->loggedIn()) {
            $this->Session->setFlash('You need to be logged to access this page.');
            $this->redirect(/* Login url. */) ;
            return ;
        }
        if ($this->Auth->user('type') != 'admin') {
            $this->Session->setFlash('You need to be admin to access this page.');
            $this->redirect(/* Somewhere... */) ;
            return ;
        }
        return parent::beforeFilter () ;
    }

}


来源:https://stackoverflow.com/questions/24636263/cakephp-auth-with-two-tables-models

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!