cakephp3で "ログイン状態の保持" の機能を実装してみました。
※Quick Start Guide http://book.cakephp.org/3.0/en/quickstart.html に追加する感じで
方針
- cookieとデータベースにログインキーを保持
- 両者が一致したらログインとする
テーブル
auto_loginテーブルを作ります
CREATE TABLE `users` (
`id` INT(11) AUTO_INCREMENT PRIMARY KEY,
`email` VARCHAR(255) NOT NULL,
`password` VARCHAR(255) NOT NULL,
`created` DATETIME,
`modified` DATETIME
);
CREATE TABLE `auto_login` (
`user_id` INT(11) UNSIGNED NOT NULL,
`auto_login_key` VARCHAR(255) NOT NULL,
PRIMARY KEY (`user_id`)
);
view
チェックボックスを追加します
login.ctp
<h1>Login</h1>
<?= $this->Form->create() ?>
<?= $this->Form->input('email') ?>
<?= $this->Form->input('password') ?>
<?= $this->Form->input('autologin', ['type' => 'checkbox']) ?>
<?= $this->Form->button('Login') ?>
<?= $this->Form->end() ?>
Controller
cookieを使うので、Cookieコンポーネントをloadします
AppController.php
$this->loadComponent('Cookie');
UserController.phpのlogin()とlogout()を修正します
UserController.php
public function login()
{
if ($this->request->is('post')) {
$user = $this->Auth->identify();
if ($user) {
if ($this->request->data('autologin') === '1') {
$this->__setupAutoLogin($user);
}
$this->Auth->setUser($user);
$this->Flash->success(__('Log In Success.'));
return $this->redirect($this->Auth->redirectUrl());
}
$this->Flash->error('Your username or password is incorrect.');
} else {
if ($autoLoginKey = $this->Cookie->read('AUTO_LOGIN')) {
$this->loadModel('AutoLogin');
$query = $this->AutoLogin->findByAutoLoginKey($autoLoginKey);
if ($query->count() > 0) {
$userId = $query->first()->user_id;
$user = $this->Users->get($userId)->toArray();
if ($user) {
// 一度ログインキーを消してから再作成する
$this->__destroyAutoLogin($user);
$this->__setupAutoLogin($user);
$this->Auth->setUser($user);
$this->Flash->success(__('Auto Log In Success.'));
return $this->redirect($this->Auth->redirectUrl());
}
}
}
}
}
public function logout()
{
$this->__destroyAutoLogin($this->Auth->user());
$this->Flash->success('You are now logged out.');
return $this->redirect($this->Auth->logout());
}
ログインキーを保存するメソッドとログインキーを削除するメソッドを実装します
UserController.php
private function __setupAutoLogin($user)
{
$this->loadModel('AutoLogin');
$autoLoginKey = sha1(uniqid() . mt_rand(1, 999999999) . '_auto_login');
$entity = $this->AutoLogin->newEntity([
'user_id' => $user['id'],
'auto_login_key' => $autoLoginKey
]);
$this->AutoLogin->save($entity);
$this->Cookie->config([
'expires' => '+7 days',
'path' => '/'
]);
$this->Cookie->write('AUTO_LOGIN', $autoLoginKey);
}
private function __destroyAutoLogin($user)
{
$this->loadModel('AutoLogin');
try {
$entity = $this->AutoLogin->get($user['id']);
if ($entity) {
$this->AutoLogin->delete($entity);
$this->Cookie->delete('AUTO_LOGIN');
}
} catch (RecordNotFoundException $e) {
$this->Cookie->delete('AUTO_LOGIN');
}
}