Home > Zend_Acl > Zend_Aclによるアクセス制御(DB編)

Zend_Aclによるアクセス制御(DB編)

intro
前回に引き続きZend_Aclによるアクセス制御を行います。今回は自分で追加したメッセージを編集できるようにします。
デモサイトより動作を確認できます。

1.テーブルの作成
この記事では以下のSQLを使用しました(MySQL)。

CREATE TABLE members
(
    id             integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
    role_id        integer        NOT NULL,
    nick_name      varchar(100)   NOT NULL,
    email          varchar(200)   NOT NULL
);
 
CREATE TABLE roles
(
    id             integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
    role_name      varchar(20)    NOT NULL,
    privileges    varchar(10)    NOT NULL
);
 
CREATE TABLE messages
(
    id             integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
    member_id      integer        NOT NULL,
    message        text           NOT NULL
);
2.コントローラの作成
以下のようにapplication/constorllers/MessageController.phpファイルを作成します。

<?php
require_once 'My/Controller/Simple.php';
require_once APP_BASE . '/models/Roles.php';
require_once APP_BASE . '/models/Members.php';
require_once APP_BASE . '/models/Messages.php';
require_once APP_BASE . '/models/forms/MessageForm.php';
require_once APP_BASE . '/models/acls/MessageAcl.php';
 
class MessageController extends My_Controller_Simple
{
    protected $_session_name = "Message";
    protected $_table_class = "Messages";
    protected $_form_class = "MessageForm";
 
    protected $_acl = null;
 
    protected function _getOutputFilter($data = null)
    {
        $messages = new Messages();
        return $messages->getOutputFilter($data);
    }
 
    public function getForm()
    {
        $form = parent::getForm();
        $form->getElement('member_id')->setValue($this->getSession()->member_id);
        return $form;
    }
 
    public function getLoginForm()
    {
        $members = new Members();
        $member_options = $members->getOptions();
 
        $form = new Zend_Form(array(
            'method'   => 'post',
            'action'   => $this->_helper->url->url(array('action'=>'index')),
            'elements' => array(
                'member' => array('select', array(
                    'required' => true,
                    'label' => 'member',
                    'multiOptions' => $member_options,
                    'validators' => array(
                        array('inArray', true, array(array_keys($member_options)))
                    ),
                )),
                'submit' => array('submit', array(
                    'label' => 'Login',
                    'decorators' => array(
                        'ViewHelper',
                        array('HtmlTag', array('tag' => 'dt', 'class' => 'submit'))
                    )
                ))
            ),
        ));
 
        return $form;
    }
 
    public function init()
    {
        parent::init();
        $this->_acl = new MessageAcl();
    }
 
    public function preDispatch()
    {
        parent::preDispatch();
        $action = $this->getRequest()->getActionName();
        $session = $this->getSession();
        if ($action != 'index' && $action != 'deny')
        {
            if (!isset($session->role))
            {
                $this->_helper->redirector('index');
            }
            else
            {
                $id = isset($session->current_id) ? $session->current_id : null;
                $id = isset($_GET['id']) ? $_GET['id'] : $id;
                $resource = $this->_acl->getResource($id, $session->member_id);
                if (!$this->_acl->isAllowed($session->role, $resource, $action))
                {
                    $this->_helper->redirector('deny');
                }
            }
        }
        $this->view->name = "message";
        $this->view->of = $this->_getOutputFilter();
    }
 
    public function indexAction()
    {
        // Select project and member
        $this->view->action = $this->getRequest()->getActionName();
        $form = $this->getLoginForm();
        $session = $this->getSession();
        if ($this->getRequest()->isPost())
        {
            if ($form->isValid($_POST))
            {
                $values = $form->getValues();
                $members = new Members();
                $member = $members->find($values['member'])->current();
                if ($member)
                {
                    $role = $member->findParentRoles();
                    if ($role)
                    {
                        $session->member_id = $values['member'];
                        $session->role = $role->role_name;
                        $this->_helper->redirector('list');
                    }
                }
            }
        }
        $this->view->form = $form;
        return $this->render('form');
    }
 
    public function denyAction()
    {
    }
}

preDispatch関数でリソースを取得し、リソースも含めアクセス権を確認するようになっています。

                $id = isset($session->current_id) ? $session->current_id : null;
                $id = isset($_GET['id']) ? $_GET['id'] : $id;
                $resource = $this->_acl->getResource($id, $session->member_id);
                if (!$this->_acl->isAllowed($session->role, $resource, $action))
3.モデルの作成
以下のようにapplication/models/acls/MessageAcl.phpファイルを作成します。

<?php
require_once 'Zend/Acl.php';
require_once 'Zend/Acl/Role.php';
require_once 'Zend/Acl/Resource.php';
require_once APP_BASE . '/models/Messages.php';
 
class MessageAcl extends Zend_Acl
{
    public function __construct()
    {
        $admin = new Zend_Acl_Role('admin');
        $user = new Zend_Acl_Role('user');
        $guest = new Zend_Acl_Role('guest');
 
        $this->addRole($admin);
        $this->addRole($guest);
        $this->addRole($user, $guest);
 
        $this->allow($admin);
 
        $this->allow($guest, null, array('list', 'detail'));
 
        // user is allowed list and view also
        $this->allow($user, null, array('add'));
 
        $messages = new Messages();
        $rowset = $messages->fetchAll();
        foreach($rowset as $row)
        {
            $resource = $this->getResource($row->id, $row->member_id, false);
            $this->add($resource);
            $this->allow($user, $resource, array('update', 'delete'));
        }
    }
 
    public function getResource($message_id, $member_id, $check = true)
    {
        if ($message_id == null || $member_id == null)
        {
            return null;
        }
        $resource_name = 'message_' . $message_id . '_' . $member_id;
        $resource = new Zend_Acl_Resource($resource_name);
        if (!$check || $this->has($resource))
        {
            return $resource;
        }
        return null;
    }
}

コンストラクタでリソースを含めてアクセス権を設定するようにしています。
その他のモデルは前回と同じです。

4.ビューの作成
ビューは前回と同じです。

5.確認
Webサーバにアクセスし、選択したメンバーにより編集などができないことを確認してください。
履歴
日付 内容
2008/5/10 公開

Comments:0

Comment Form
Remember personal info

Trackbacks:0

Trackback URL for this entry
http://www.oplabo.jp/article/45/trackback
Listed below are links to weblogs that reference
Zend_Aclによるアクセス制御(DB編) from Open Programming Laboratory

Home > Zend_Acl > Zend_Aclによるアクセス制御(DB編)

English
Search
Feeds

Return to page top