CakePHP3めも

以下のプラグインを導入すればアクセス管理の幅が広がります。

参考
http://qiita.com/eiroh/items/f37a70a35103de6c6a1b

テーブルの作成

users, groupsテーブルを作成します。 参考
http://book.cakephp.org/2.0/ja/tutorials-and-examples/simple-acl-controlled-application/simple-acl-controlled-application.html#id1

bakeしてプログラム類を自動生成します。

$ bin/cake bake all users
$ bin/cake bake all groups

プラグインのインストール

composer.jsonに2行追加します。

    "require": {
        "php": ">=5.5.9",
        "cakephp/cakephp": "3.3.*",
        "mobiledetect/mobiledetectlib": "2.*",
        "cakephp/migrations": "~1.0",
        "cakephp/plugin-installer": "*",
        "cakephp/acl": "dev-master",
        "jcpires/cakephp3-aclmanager": "dev-master"
    },
# /usr/local/bin/composer.phar update

記述の追加

bootstrap.php

config/bootstrap.php に追加します。

Plugin::load('Acl', ['bootstrap' => true]);

AppController.php

<?php
namespace App\Controller;

use Cake\Controller\Controller;
use Cake\Event\Event;
use Cake\Controller\ComponentRegistry;
use Acl\Controller\Component\AclComponent;

class AppController extends Controller
{
    public function beforeFilter(Event $event)
    {
        $this->Auth->allow();
    }

    public function initialize()
    {
        parent::initialize();

        $this->loadComponent('RequestHandler');
        $this->loadComponent('Flash');
        $this->loadComponent('Acl.Acl');
        $this->loadComponent('Auth', [
            'authorize' => 'Controller',
            'unauthorizedRedirect' => false,
            'authError' => 'アクセス権限がありません',
        ]);
    }

    public function beforeRender(Event $event)
    {
        if (!array_key_exists('_serialize', $this->viewVars) &&
            in_array($this->response->type(), ['application/json', 'application/xml'])
        ) {
            $this->set('_serialize', true);
        }
    }

    public function isAuthorized($user)
    {
        $Collection = new ComponentRegistry();
        $acl = new AclComponent($Collection);
        $controller = $this->request->controller;
        $action     = $this->request->action;
        return $acl->check(['Users' => ['id' => $user['id']]], "$controller/$action");
    }
}

GroupsController.php

変更していないfunctionは省いています。

<?php
namespace App\Controller;

use App\Controller\AppController;
use Cake\Event\Event;
use JcPires\AclManager\Event\PermissionsEditor;

class GroupsController extends AppController
{
    public $helpers = [
        'AclManager' => [
            'className' => 'JcPires/AclManager.AclManager'
        ]
    ];

    public function add()
    {
        $group = $this->Groups->newEntity();
        if ($this->request->is('post')) {
            $group = $this->Groups->patchEntity($group, $this->request->data);
            if ($this->Groups->save($group)) {
                $this->Flash->success(__('The group has been saved.'));

                return $this->redirect(['action' => 'index']);
            } else {
                $this->Flash->error(__('The group could not be saved. Please, try again.'));
            }
        }
        $this->set(compact('group'));
        $this->set('_serialize', ['group']);
    }

    public function edit($id = null)
    {
        $group = $this->Groups->get($id, [
            'contain' => []
        ]);

        $this->loadComponent('JcPires/AclManager.AclManager');
        $EditablePerms = $this->AclManager->getFormActions();

        if ($this->request->is(['patch', 'post', 'put'])) {
            $group = $this->Groups->patchEntity($group, $this->request->data);
            if ($this->Groups->save($group)) {
                $this->eventManager()->on(new PermissionsEditor());
                $perms = new Event('Permissions.editPerms', $this, [
                    'Aro' => $group,
                    'datas' => $this->request->data
                ]);
                $this->eventManager()->dispatch($perms);

                $this->Flash->success(__('The group has been saved.'));

                return $this->redirect(['action' => 'index']);
            } else {
                $this->Flash->error(__('The group could not be saved. Please, try again.'));
            }
        }
        $this->set(compact('group', 'EditablePerms'));
        $this->set('_serialize', ['group', 'EditablePerms']);
    }
}

UsersController.php

変更していないfunctionは省いています。

<?php
namespace App\Controller;

use App\Controller\AppController;
use Cake\Event\Event;

class UsersController extends AppController
{
    public function beforeFilter(Event $event)
    {
        parent::beforeFilter($event);
        $this->Auth->allow(['login']);
    }

    public function login()
    {
        if ($this->request->is('post')) {
            $user = $this->Auth->identify();

            if ($user) {
                $this->Auth->setUser($user);
                return $this->redirect($this->Auth->redirectUrl());
            }
            $this->Flash->error(__('Invalid username or password, try again'));
        }
    }

    public function logout()
    {
        return $this->redirect($this->Auth->logout());
    }

Group.php

    public function parentNode()
    {
        return null;
    }

User.php

use Cake\ORM\TableRegistry;
use Cake\Auth\DefaultPasswordHasher;
    protected function _setPassword($password)
    {
        return (new DefaultPasswordHasher)->hash($password);
    }

    public function parentNode()
    {
        if (!$this->id) {
            return null;
        }
        if (isset($this->group_id)) {
            $group_id = $this->group_id;
        } else {
            $users_table = TableRegistry::get('Users');
            $user = $users_table->find('all', ['fields' => ['group_id']])->where(['id' => $this->id])->first();
            $group_id = $user->group_id;
        }
        if (!$group_id) {
            return null;
        }

        return ['Groups' => ['id' => $group_id]];
    }

Groups.php

$this->addBehavior('Acl.Acl', ['type' => 'requester']);

Users.php

$this->addBehavior('Acl.Acl', ['type' => 'requester']);

Groups/edit.ctp

    <?= $this->Form->create($group) ?>
    <fieldset>
        <legend><?= __('Edit Group') ?></legend>
        <?php
            echo $this->Form->input('name');
        ?>
        <?php foreach ($EditablePerms as $Acos) :?>
            <?php foreach ($Acos as $controllerPath => $actions) :?>
                <?php if (!empty($actions)) :?>
                    <h4><?= $controllerPath ;?></h4>
                    <?php foreach ($actions as $action) :?>
                        <?php ($this->AclManager->checkGroup($group, $controllerPath.'/'.$action)) ? $val = 1 : $val = 0 ?>
                        <?= $this->Form->label($controllerPath.'/'.$action, $action);?>
                        <?= $this->Form->select($controllerPath.'/'.$action, [0 => 'No', 1 => 'Yes'], ['value' => $val]) ;?>
                    <?php endforeach ;?>
                <?php endif;?>
            <?php endforeach ;?>
        <?php endforeach ;?>
    </fieldset>
    <?= $this->Form->button(__('Submit')) ?>
    <?= $this->Form->end() ?>

Users/login.ctp

<div class="users form">
<?= $this->Flash->render('auth') ?>
<?= $this->Form->create() ?>
    <fieldset>
        <legend><?= __('Please enter your username and password') ?></legend>
        <?= $this->Form->input('username') ?>
        <?= $this->Form->input('password') ?>
    </fieldset>
<?= $this->Form->button(__('Login')); ?>
<?= $this->Form->end() ?>
</div>

aclテーブルの作成

$ bin/cake Migrations.migrations migrate -p Acl

Acoデータの作成

$ bin/cake acl_extras aco_sync
$ bin/cake acl create aco controllers App
$ bin/cake acl create aco App isAuthorized

確認

$ bin/cake acl view aco

グループとユーザーの登録

グループを登録

http://localhost/groups/add

グループの権限設定

http://localhost/groups/edit/1

ユーザーの登録

http://localhost/users/add

動作確認

ログアウト

http://localhost/users/logout

AppController.phpの一部をコメント化

#$this->Auth->allow();

リダイレクトされることを確認

http://localhost/ へアクセスすると http://localhost/users/login へリダイレクトされる

他にも設定した権限通りに動作するか確認します。

ControllerやActionを追加した際の更新方法

$ bin/cake acl_extras aco_update

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2016-09-27 (火) 09:27:39 (1055d)