0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CakePHPで認証処理

Last updated at Posted at 2025-08-13

前回からの続き

やはり認証処理は試しておかないという事で、前回作ったアプリにログインの仕組みを追加していきます。

ということで、前回、Userコントローラじゃなくて、AddressBookコントローラとかにしとけば良かったなぁと後悔していますが、とりあえず、前回は前回で、折角作ったメール機能ガン無視でログインの仕組みを追加していきます。

認証プラグインの追加

てっきり初めから入っていると思いましたが、認証機能はプラグインを追加でインストールするようです。
Dockerのコンテナから以下のコマンドを実行します。

> docker exec -it php_svr /bin/bash

/var/www/html# cd testapp
/var/www/html/testapp# composer require cakephp/authentication

ちなみに日本語訳のドキュメントは記述が古く、ここでauthentication:2.0とバージョンを指定してしまうとエラーになります。
というか???と思い英語のドキュメントを確認したら全然違いますね。
なんだか若干シンプルになってます。

テストプログラムの改造

テーブルにpasswordフィールド追加

やり方はいろいろあるとは思いますが、今回もDB関係は雑な説明で、最終的に以下のテーブルとなるようにテーブル変更してください。

 CREATE TABLE users
 (
     id INT NOT NULL AUTO_INCREMENT,
     name VARCHAR(32),
     email VARCHAR(255),
+    password VARCHAR(255),
     PRIMARY KEY (id)
 );

Application に認証に仕組み追加

ドキュメントに従い、ただただ無心にコードを追加していきます。

ファイル名:src/Application.php

use Authentication\AuthenticationService;
use Authentication\AuthenticationServiceInterface;
use Authentication\AuthenticationServiceProviderInterface;
use Authentication\Identifier\AbstractIdentifier;
use Authentication\Identifier\IdentifierInterface;
use Authentication\Middleware\AuthenticationMiddleware;
use Cake\Http\MiddlewareQueue;
use Cake\Routing\Router;
use Psr\Http\Message\ServerRequestInterface;
class Application extends BaseApplication implements AuthenticationServiceProviderInterface
public function bootstrap(): void
{
    parent::bootstrap();

+    $this->addPlugin('Authentication');
        :
public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue
{
    $middlewareQueue
        :
        ->add(new BodyParserMiddleware())

+        // Add the AuthenticationMiddleware. It should be
+        // after routing and body parser.
+        >add(new AuthenticationMiddleware($this))
        :
/**
 * Returns a service provider instance.
 *
 * @param \Psr\Http\Message\ServerRequestInterface $request Request
 * @return \Authentication\AuthenticationServiceInterface
 */
public function getAuthenticationService(ServerRequestInterface $request): AuthenticationServiceInterface
{
    $service = new AuthenticationService();

    // Define where users should be redirected to when they are not authenticated
    $service->setConfig([
        'unauthenticatedRedirect' => [
                'prefix' => false,
                'plugin' => false,
                'controller' => 'Users',
                'action' => 'login',
        ],
        'queryParam' => 'redirect',
    ]);

    // Define identifiers
    $fields = [
        AbstractIdentifier::CREDENTIAL_USERNAME => 'email',
        AbstractIdentifier::CREDENTIAL_PASSWORD => 'password'
    ];
    $passwordIdentifier = [
        'Authentication.Password' => [
            'fields' => $fields,
        ],
    ];

    // Load the authenticators. Session should be first.
    $service->loadAuthenticator('Authentication.Session', [
        'identifier' => $passwordIdentifier,
    ]);
    $service->loadAuthenticator('Authentication.Form', [
        'identifier' => $passwordIdentifier,
        'fields' => $fields,
        'loginUrl' => Router::url([
            'prefix' => false,
            'plugin' => null,
            'controller' => 'Users',
            'action' => 'login',
        ]),
    ]);

    return $service;
}

AppController に認証に仕組み追加

ドキュメントに従い、ただただ無心にコードを追加していきます。

ファイル名:src/Controller/AppController.php

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

    $this->loadComponent('Flash');

+   $this->loadComponent('Authentication.Authentication');
    :

ここで公式のドキュメントでは、viewとindexはログイン無しで表示できるようにと細工してますが、ログインしない子には内容は一切見せないぞと、そんな仕組みは追加しません。
ちなみにこの部分です。

// in a controller beforeFilter or initialize
// Make view and index not require a logged in user.
$this->Authentication->allowUnauthenticated(['view', 'index']);

コントローラにログイン機能追加

ドキュメントに従い、ただただ無心にコードを追加していきます。

ファイル名:src/Controller/UsersController.php

public function login()
{
    $result = $this->Authentication->getResult();
    // If the user is logged in send them away.
    if ($result && $result->isValid()) {
        $target = $this->Authentication->getLoginRedirect() ?? '/index';
        return $this->redirect($target);
    }
    if ($this->request->is('post')) {
        $this->Flash->error('Invalid username or password');
    }
}

public function logout()
{
    $this->Authentication->logout();
    return $this->redirect(['controller' => 'Users', 'action' => 'login']);
}

とは言え、これではログインしないと何も表示できなくなるので、loginとaddは見えるようにします。

public function beforeFilter(\Cake\Event\EventInterface $event)
{
    parent::beforeFilter($event);

+    $this->Authentication->allowUnauthenticated(['login', 'add']);
}

公式ドキュメントではloginのみ許可してますが、パスワード、たぶんハッシュ化してるのに、ユーザ追加ページ使えないとテストできないよって感じです。
あくまでテスト用なので、addも許可しときます。

あとはビューを作ります。

ドキュメントに従い、ただただ...(いい加減しつこい)

ファイル名:templates/Users/login.php

<!-- in /templates/Users/login.php -->
<div class="users form">
    <?= $this->Flash->render() ?>
    <h3>Login</h3>
    <?= $this->Form->create() ?>
    <fieldset>
        <legend><?= __('ユーザー名とパスワードを入力してください') ?></legend>
        <?= $this->Form->control('email', ['required' => true]) ?>
        <?= $this->Form->control('password', ['required' => true]) ?>
    </fieldset>
    <?= $this->Form->submit(__('Login')); ?>
    <?= $this->Form->end() ?>

    <?= $this->Html->link("Add User", ['action' => 'add']) ?>
</div>

ファイル名:templates/Users/add.php

    :
                <?php
                    echo $this->Form->control('name');
                    echo $this->Form->control('email');
+                   echo $this->Form->control('password');
                ?>
    :

最後にパスワードのハッシュ化の設定

ユーザーを追加するときに、パスワードはハッシュ化してからDBに保存します。
平文のままパスワード保存するとか、ありえないです。
そんな恐ろしい時代ははるか昔に終わったと信じてます。ん?

+ use Authentication\PasswordHasher\DefaultPasswordHasher;

class User extends Entity
{
    :
+   // Automatically hash passwords when they are changed.
+   protected function _setPassword(string $password)
+   {
+       $hasher = new DefaultPasswordHasher();
+       return $hasher->hash($password);
+   }
}

以上で、ログインしてない状態でアクセスするとログインページに飛ばされるようになります。

ログオフはボタン増やしてないので、とりあえず、URL直打ちで
http://localhost:8080/testapp/users/logout/」
とすればログイン画面に戻ります。

最後に

公式ドキュメントに従って、無心でコードを追加するだけで、簡単に認証機能が追加できました。
最初日本語訳読んで、苦労したのは内緒です。最新バージョン使ってるときは、最初から英語版読むべきですね。

0
0
0

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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?