m_shige1979のときどきITブログ

プログラムの勉強をしながら学習したことや経験したことをぼそぼそと書いていきます

Github(変なおっさんの顔でるので気をつけてね)

https://github.com/mshige1979

cakephp3でfinderでログイン条件を追加

cakephp3になってからというか少しずつ変化しているものがあります

認証処理とかも…

環境

CensOS7.x
php 7.0.3
cakephp3.2.3

認証処理で条件を付ける際にfinderを使う

以前は"scope"がありましたがそれとは別に"finder"というものがあります。
Usersテーブルとは別にテーブルのチェックなどが必要な場合はこちらがあると便利な感じ

実装

AppController

src/Controller/AppController.php

<?php
namespace App\Controller;

use Cake\Controller\Controller;
use Cake\Event\Event;

class AppController extends Controller
{

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

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

        // 認証コンポーネント
        $this->loadComponent('Auth', [
            // ログイン後のリダイレクト
            'loginRedirect' => [
                'controller' => 'Posts',
                'action' => 'index'
            ],
            // ログアウト後のリダイレクト
            'logoutRedirect' => [
                'controller' => 'Users',
                'action' => 'login',
            ],
            // 認証
            'authenticate' => [
                // フォーム認証
                'Form' => [
                    // 暗号化
                    'passwordHasher' => [
                        'className' => 'Default',
                    ],
                    // 認証フィールド
                    'fields' => [
                        'username' => 'username',
                        'password' => 'password'
                    ],
                    // モデル
                    'userModel' => 'Users',
                    // 抽出メソッド
                    'finder' => 'login'
                ]
            ],
            // データ保存
            'storage' => 'Session',

            // 権限
            // isAuthorizedメソッドを実装する必要がある
            'authorize' => ['Controller'],
        ]);
    }

    /**
     * アクション前処理
     * @param Event $event
     */
    public function beforeFilter(Event $event)
    {
        parent::beforeFilter($event);
    }

    /**
     * Before render callback.
     *
     * @param \Cake\Event\Event $event The beforeRender event.
     * @return void
     */
    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);
        }
    }

    /**
     * 認証権限判定処理
     *
     * @param $user
     * @return bool
     */
    public function isAuthorized($user)
    {
        // ユーザーの権限が"admin"の場合は全てを許可する
        if (isset($user['role']) && $user['role'] === 'admin') {
            return true;
        }

        // Default deny
        return false;
    }
}

※finderという項目に"login"を指定します。省略時は"all"

UsersTable.php

src/Model/Table/UsersTable.php

<?php
namespace App\Model\Table;

use App\Model\Entity\User;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;

/**
 * Users Model
 *
 */
class UsersTable extends Table
{

    /**
     * Initialize method
     *
     * @param array $config The configuration for the Table.
     * @return void
     */
    public function initialize(array $config)
    {
        parent::initialize($config);

        $this->table('users');
        $this->displayField('id');
        $this->primaryKey('id');

        $this->addBehavior('Timestamp');
    }

    /**
     * ログイン用メソッド
     *
     * 独自のfindメソッド
     * @param Query $query
     * @param array $options
     * @return Query
     */
    public function findLogin(Query $query, array $options){
        // 条件を付与
        $query->where([
            'Users.status' => 0,
            'Users.deleted' => 0
        ]);
        return $query;
    }

}

SQLのログ

SELECT 
    Users.id AS `Users__id`, 
    Users.username AS `Users__username`, 
    Users.password AS `Users__password`, 
    Users.role AS `Users__role`, 
    Users.status AS `Users__status`, 
    Users.deleted AS `Users__deleted`, 
    Users.created AS `Users__created`, 
    Users.modified AS `Users__modified` 
FROM 
    users Users 
WHERE 
    (
        Users.username = 'test01' 
        AND Users.status = 0 
        AND Users.deleted = 0
    ) 
LIMIT 1

所感

HTMLのヘルパーって使いたくない…
生成されるまでどんな形かわからないんですよ…
多少手間がかかってもHTMLで書くべきかと思います…

なんでHTMLヘルパーってあるんだろう…