12

5 月に、私はこの質問を投稿しました。別のアプリで同じことをやり直そうとしていますが、この問題の解決策が見つかりません。私はより多くの情報とより良いコードを持っているので、皆さんがこれを整理するのを手伝ってくれることを願っています.

ユースケース: 診療所には、管理者ユーザーがいる Web サイトがあります。ユーザーは、Userモデルとを介して CakePHP の Auth で正常にログインしますUsersController

医師は、まったく異なるプロファイルとアクションを持つ医師を紹介しています。医師は からログインする必要がありますexample.com/physicians/login。ただし、このログインはこれで失敗しています

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

ここに私のコードがあります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',
                '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 に切り替えたくありません。たった 2 回のログインでそれが必要かどうかはわかりません。助けていただければ幸いです。

編集:以下のジョシュアの答えは素晴らしく、非常に役に立ちます。実装しましたが、/phys/physican/login (prefix/controller/action) 経由で Physician としてログインしようとすると、まだ不正なエラーが発生します。管理者のセットアップはうまく機能します。ログインしようとしたときのデバッグコードは次のとおりです。

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()

}

4

2 に答える 2

19

OK、私はそれを行う方法を持っています。プレフィックスルーティングについて知っていますか? そうでない場合は、ここで私の回答を読んでください: CakePHP/MVC 管理機能の配置その回答は、単一のルーティング プレフィックス ('admin') を設定する方法を説明しています。ただし、次のように、任意の数を指定できます。

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

できることは、すべての医師のメソッドで「admin」プレフィックス ルーティングを使用し、すべての医師のメソッドで「phys」プレフィックス ルーティングを使用することです。

以下は、私がすぐにハックしたコードなので、完璧ではないかもしれませんが、概念を示すはずです。これは、アプリ コントローラーの before フィルター メソッドの擬似コードです。

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','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

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

これにより、1 つのブラウザで医師と管理者の両方として、互いのセッションに干渉することなくログインできるようになります。実際のサイトでは必要ないかもしれませんが、テスト中は確かに便利です。

ここで、それぞれのコントローラーで、適切なプレフィックスを使用して、簡単なログイン/ログアウト メソッドが必要になります。

したがって、管理者のプレフィックスについては、ユーザーコントローラーで次のようにします。

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());
}

私が言ったように、私がすべてのコードを非常に迅速にまとめたので、そのままでは機能しないかもしれませんが、コンセプトは示されているはずです。ご不明な点がございましたら、お知らせください。

于 2012-10-31T22:07:17.570 に答える
0

それ以外の

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

あなたが使用する必要があります

setcookie("keys", value);
于 2015-03-25T06:21:14.303 に答える