CakePHP 4.0.0-RC2 でユーザー認証を実装

はじめに

今日は CakePHP 4.0.0-RC2 でユーザー認証をする方法をご紹介します。

CakePHP
4.0.0-RC2
XAMPP
7.3.11
PHP
7.3.11
MariaDB
10.4.8
OS
Win 10 Home 64Bit
目次
  1. ユーザー情報の準備
  2. authentication プラグインはまだ使えず
  3. AuthComponent で実装
  4. おわりに

1. ユーザー情報の準備

1-1. テーブル作成

下記 SQL で users テーブルを作成します。今回はテストプログラムなので、非常にシンプルな構成です。

CREATE TABLE `users` (
  `id` int(10) UNSIGNED NOT NULL,
  `username` varchar(255) NOT NULL,
  `password` varchar(255) NOT NULL,
  `created` datetime NOT NULL,
  `modified` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

ALTER TABLE `users`
  ADD PRIMARY KEY (`id`),
  MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT;

1-2. ユーザー関連機能を Bake

テスト用ユーザーを登録するためにフォームを作成します。
今回は bake all で生成しました。

> cd \path\to\cakephp4
> bin\cake bake all users

1-3. パスワードのハッシュ化

上記 Bake で生成したフォームから登録すると、パスワードが平文になってしまいます。
エンティティに下記を追加し、ハッシュ化して保存するようにします。

/src/Model/Entity/User.php
<?php
declare(strict_types=1);

namespace App\Model\Entity;

use Cake\Auth\DefaultPasswordHasher; // ← これを追加
use Cake\ORM\Entity;

class User extends Entity
{
  // ~~~省略~~~

  // ↓これを追加
  protected function _setPassword(string $password)
  {
    if (strlen($password) === 0) {
      return null;
    }

    return (new DefaultPasswordHasher)->hash($password);
  }
}

1-4. ユーザー情報の登録

Bake で生成したユーザー登録画面を開き、テスト用ユーザーを登録してください。

URL は https://example.com/users/add のような感じです。

2. authentication プラグインはまだ使えず

CakePHP 4 からは AuthComponent は非推奨になり、代わりに cakephp/authentication プラグインの使用が望ましいとされています。

しかし comopser でインストールしようとしたら、エラーになりました。

> composer require cakephp/authentication

Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Installation request for cakephp/authentication ^1.4 -> satisfiable by cakephp/authentication[1.4.0].
    - Conclusion: remove cakephp/cakephp 4.x-dev
    - Conclusion: don't install cakephp/cakephp 4.x-dev
    - cakephp/authentication 1.4.0 requires cakephp/core ^3.7 -> satisfiable by cakephp/core[3.7.0, 3.7.0-RC1, 3.7.0-RC2, 3.7.0-RC3, 3.7.0-beta1, 3.7.1, 3.7.2, 3.7.3, 3.7.4, 3.7.5, 3.7.6, 3.7.7, 3.7.8, 3.7.9, 3.8.0, 3.8.0-RC1, 3.8.0-RC2, 3.8.0-RC3, 3.8.0-beta1, 3.8.1, 3.8.2, 3.8.3, 3.8.4, 3.8.5, 3.8.6].

~~~省略~~~

無理やりインストールする方法もあるのかな、とも思ったのですが、今回は AuthComponent で実装することにしました。

3. 従来の AuthComponent で実装

3-1. AppController で AuthComponent 読込み

参考にしたのは CakePHP 3 のドキュメントです。

AppController の initialize() に下記を追加します。

/src/Controller/AppController.php
public function initialize(): void
{
  // ~~~ 省略 ~~~

  // これを追加
  $this->loadComponent('Auth', [
    // ログイン後に遷移するアクション
    'loginRedirect' => [
        'controller' => 'Pages',
        'action' => 'home'
    ],
    // ログアウトした後に遷移するアクション
    'logoutRedirect' => [
        'controller' => 'Users',
        'action' => 'login'
    ]
  ]);
}

3-2. UsersController に設定と login / logout アクションを追加

UsersController に下記を追記します。今回は Users コントローラの logout アクションのみ許可しています。
公式ドキュメントによると、ログイン不要なアクションを指定する $this->Auth->allow() には login アクションを含めてはいけません

/src/Controller/UsersController.php
<?php
declare(strict_types=1);

namespace App\Controller;

use Cake\Event\EventInterface; // ←これを追加。ドキュメントと異なるので注意

class UsersController extends AppController
{
  // これを追加。引数の型が EventInterface なので注意
  public function beforeFilter(EventInterface $event)
  {
      parent::beforeFilter($event);
      // ログインなしでアクセスできるアクション
      $this->Auth->allow(['logout']);
  }

  // ~~~ 省略 ~~~
}

上記コードを CakePHP 3 のドキュメント通りに、use \Cake\Event\Event; で実装したら下記エラーがでました。このメッセージに従い EventInterface に変更しています。

Declaration of App\Controller\UsersController::beforeFilter(Cake\Event\Event $event) should be compatible with Cake\Controller\Controller::beforeFilter(Cake\Event\EventInterface $event)

次に、同じく UsersController に、下記 login() と logout() のアクションを追加します。

/src/Controller/UsersController.php
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());
}

3-3. ログイン画面のテンプレートを追加

最後に template/Users に 下記 login.php を追加します。

src/template/login.php
<?= $this->Flash->render() ?>
<?= $this->Form->create() ?>
  <h1><?= __('Please enter your username and password') ?></h1>
  <div>
    <?= $this->Form->control('username') ?>
    <?= $this->Form->control('password') ?>
  </div>
  <?= $this->Form->button(__('Login')); ?>
<?= $this->Form->end() ?>

これで実装は完了です。https://example.com/ などにアクセスし、ログイン画面に遷移することと、登録したユーザー情報でログインできるか試してみてください。

4. おわりに

CakePHP 4 のユーザー認証では authentication プラグインが推奨されていますが、composer でのインストールはまだ出来ませんでした。

Auth コンポーネントによる認証は、CakePHP 3 用コードの大部分を流用することができました。CakePHP 3 から 4 への移行を少しでも早く終わらせたい場合には、Auth コンポーネントによる認証であれば短時間で実装できそうです。