私は現在ACLを必要とするサイトで作業しており、Zendを使用しているので、ACLクラスを使用することは理にかなっていますが、これを行う方法についてはほとんどまたはまったくわかりません。ドキュメントを読みましたが、さらに混乱しました...基本的に私がやりたいのは、2つのユーザーグループを設定することだけです。 「通常」および「管理者」、通常のユーザーは管理者ではないコントローラーを持つすべてのページにアクセスできますが、管理者は明らかに管理者コントローラーページにアクセスできます。
私は多くの質問があります:
ウェブサイトや良いチュートリアルに案内していただければ幸いです。
少し前に同じようなことを実装しました。基本的な概念は、サンプルコードに続きます。
bootstrapファイル(私の場合はindex.php)にロードされる独自のconfigAcl.phpファイルを作成しました。ケースに応じて次のようになります。
$acl = new Zend_Acl();
$roles = array('admin', 'normal');
// Controller script names. You have to add all of them if credential check
// is global to your application.
$controllers = array('auth', 'index', 'news', 'admin');
foreach ($roles as $role) {
$acl->addRole(new Zend_Acl_Role($role));
}
foreach ($controllers as $controller) {
$acl->add(new Zend_Acl_Resource($controller));
}
// Here comes credential definiton for admin user.
$acl->allow('admin'); // Has access to everything.
// Here comes credential definition for normal user.
$acl->allow('normal'); // Has access to everything...
$acl->deny('normal', 'admin'); // ... except the admin controller.
// Finally I store whole ACL definition to registry for use
// in AuthPlugin plugin.
$registry = Zend_Registry::getInstance();
$registry->set('acl', $acl);
もう1つのケースは、すべてのコントローラーで通常のユーザーのみの「リスト」アクションを許可する場合です。非常に簡単です。次のような行を追加します。
$acl->allow('normal', null, 'list'); // Has access to all controller list actions.
次に、コントローラーアクションの要求があったときに、資格情報のチェックを自動的に処理する新しいプラグインを作成する必要があります。このチェックは、コントローラーアクションを呼び出す前に呼び出されるpreDispatch()メソッドで行われます。
AuthPlugin.phpは次のとおりです。
class AuthPlugin extends Zend_Controller_Plugin_Abstract
{
public function preDispatch(Zend_Controller_Request_Abstract $request)
{
$loginController = 'auth';
$loginAction = 'login';
$auth = Zend_Auth::getInstance();
// If user is not logged in and is not requesting login page
// - redirect to login page.
if (!$auth->hasIdentity()
&& $request->getControllerName() != $loginController
&& $request->getActionName() != $loginAction) {
$redirector = Zend_Controller_Action_HelperBroker::getStaticHelper('Redirector');
$redirector->gotoSimpleAndExit($loginAction, $loginController);
}
// User is logged in or on login page.
if ($auth->hasIdentity()) {
// Is logged in
// Let's check the credential
$registry = Zend_Registry::getInstance();
$acl = $registry->get('acl');
$identity = $auth->getIdentity();
// role is a column in the user table (database)
$isAllowed = $acl->isAllowed($identity->role,
$request->getControllerName(),
$request->getActionName());
if (!$isAllowed) {
$redirector = Zend_Controller_Action_HelperBroker::getStaticHelper('Redirector');
$redirector->gotoUrlAndExit('/');
}
}
}
}
最後のステップは、configAcl.phpをロードし、AuthPluginをbootstrapファイル(おそらくindex.php)に登録することです。
require_once '../application/configAcl.php';
$frontController = Zend_Controller_Front::getInstance();
$frontController->registerPlugin(new AuthPlugin());
これが基本的な考え方です。私は上記のコードをテストしなかったので(ショーケースの目的のためだけにコピーアンドペーストして書き直しました)、防弾ではありません。ただアイデアを与えるために。
[〜#〜]編集[〜#〜]
明確にするために。上記のAuthPluginのコードは、$ identityオブジェクトがユーザーデータ(データベースの「role」列)で埋められていることを前提としています。これは、次のようなログインプロセス内で実行できます。
[...]
$authAdapter = new Zend_Auth_Adapter_DbTable($db);
$authAdapter->setTableName('Users');
$authAdapter->setIdentityColumn('username');
$authAdapter->setCredentialColumn('password');
$authAdapter->setIdentity($username);
$authAdapter->setCredential(sha1($password));
$authAdapter->setCredentialTreatment('? AND active = 1');
$auth = Zend_Auth::getInstance();
$result = $auth->authenticate($authAdapter);
if ($result->isValid()) {
$data = $authAdapter->getResultRowObject(null, 'password'); // without password
$auth->getStorage()->write($data);
[...]
このソリューションは、Zend_Aclの最も単純な実装であることがわかる場合があります。
例:
class UserController extends Zend_Controller_Action {
public function preDispatch(){
$resource = 'user_area';
$privilege = $this->_request->getActionName();
if (!$this->_helper->acl($resource, $privilege)) $this->_redirect();
}
}
Zend/Controller/Action/Helper/Acl.php
class Zend_Controller_Action_Helper_Acl extends Zend_Controller_Action_Helper_Abstract {
protected $acl;
protected $role;
protected function getAcl(){
if (is_null($this->acl)){
$acl = new Zend_Acl();
$acl->addResource(new Zend_Acl_Resource('user_area'));
$acl->addResource(new Zend_Acl_Resource('customer_area'), 'user_area');
$acl->addResource(new Zend_Acl_Resource('web_area'));
$acl->addRole(new Zend_Acl_Role('guest'));
$acl->addRole(new Zend_Acl_Role('user'), 'guest');
$acl->allow('guest', 'web_area');
$acl->allow('guest', 'user_area', array(
'forgot-password',
'login'
));
$acl->allow('user', 'user_area');
$acl->allow('customer', 'customer_area');
$this->acl = $acl;
}
return $this->acl;
}
protected function getRole(){
if (is_null($this->role)){
$session = new Zend_Session_Namespace('session');
$role = (isset($session->userType)) ? $session->userType : 'guest';
$this->role = $role;
}
return $this->role;
}
public function direct($resource, $privilege = null){
$acl = $this->getAcl();
$role = $this->getRole();
$allowed = $acl->isAllowed($role, $resource, $privilege);
return $allowed;
}
}
この構造で遊んでください。データベースからロールとリソースを取得し、これをセッションまたはキャッシュに保存します。