備考
- 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>