LoginSignup
10

More than 5 years have passed since last update.

CakePHP3でユーザ認証を設定する

Last updated at Posted at 2017-09-16

備考

  • postgresqlをDBとして利用
  • emailをログインIDとして使う
  • CakePHP 3.4を利用

ユーザ用のテーブルを作成

create_users.sql
CREATE TABLE users (
    id        SERIAL       PRIMARY KEY,
    email     VARCHAR(255) NOT NULL, 
    password  VARCHAR(255) NOT NULL,
    lastname  VARCHAR(255) NOT NULL,
    firstname VARCHAR(255) NOT NULL, 
    role      VARCHAR(20)  NOT NULL,
    created   TIMESTAMP    NOT NULL DEFAULT NOW(), 
    modified  TIMESTAMP
);

bakeでコード生成

cd /var/www/html/app/bin
./cake bake all Users

bakeで生成されたコードを修正

エンティティ

パスワードを保存する際、生の値ではなくハッシュを保存するように変更:

Model/Entity/User.php
use Cake\Auth\DefaultPasswordHasher; // 追加

    // (他のコード)

    /**
     * パスワードのhashを保存する
     */
    protected function _setPassword($password)
    {
        if (strlen($password) > 0) {
            return (new DefaultPasswordHasher)->hash($password);
        }
    }

AppController.php

Authコンポーネントの読み込みを実施。
その際、ログインIDにUsers.emailを用いることを指定。
またisAuthorizedメソッドを追加し、管理者ロールのユーザに全機能のアクセスを開放、
その他のロールの場合はデフォルトで拒否とする(許可したい場合は各コントローラで個別に設定)

Controller/AppController.php
    public function initialize()
    {
        parent::initialize();

        $this->loadComponent('RequestHandler');
        $this->loadComponent('Flash');

        /*
         * Enable the following components for recommended CakePHP security settings.
         * see http://book.cakephp.org/3.0/en/controllers/components/security.html
         */
        $this->loadComponent('Security');
        $this->loadComponent('Csrf');

        $this->loadComponent('Auth', [
            'authorize'      => [ 'Controller'],
            'authenticate'   => [ 'Form' => [ 'fields' => ['username' => 'email', 'password' => 'password' ] ] ],
            'loginRedirect'  => [ 'controller' => 'Articles' , 'action' => 'index' ],
            'logoutRedirect' => [ 'controller' => 'Users'    , 'action' => 'login' ],
            'loginAction'    => '/users/login',
            'authError'      => 'Login required'
        ]);

    }

    public function isAuthorized($user)
    {
        // Admin can access every action
        if (isset($user['role']) && $user['role'] === 'admin') {
            return true;
        }

        // Default deny
        return false;
    }

コントローラ

ログイン、ログアウト用のアクションを追加。
また認証不要なアクションを$this->Auth->allowで定義

Controller/UsersController.php

use Cake\Event\Event; // 追加

    /**
     * 認証不要なアクションを定義
     */
    public function beforeFilter(Event $event)
    {
        parent::beforeFilter($event);
        // ここにloginを追加してはならない
        // ソース:https://book.cakephp.org/3.0/en/tutorials-and-examples/blog-auth-example/auth.html
        $this->Auth->allow(['add', 'logout']);
    }

    /**
     * role別にアクセスを制御したい場合はここに記述。全ロールに許可する場合はreturn trueとだけ書く
     */
    public function isAuthorized($user)
    {
        return true;
    }

    /**
     * ログインアクション
     */
    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());
    }

ログイン用のテンプレート作成

Template/Users/login.ctp

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

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10