パスワード変更を実装する【CakePHP4】

やりたいこと・前提

以下のような流れの、パスワード更新フォームを作るとします。

①フォームから、元パスワードと新パスワードを送信

①現パスワードの一致チェック

②新パスワードを登録

前提

公式の「シンプルな認証と認可のアプリケーション」を参考に、ログイン・ログアウトの仕組みが実装されている。

コード

フォーム(template)

template/users/changePassword.php

<form method="post">
      <input type="password"  name="password">
      <input type="password"  name="new-password">
      <input type="submit" value="送信する">
     //パスワード不一致時には、以下にエラー表示する。
      <p><?= $error ?></p>
    </form>

シンプルに、現パスワードと新パスワードを送信するフォームです。

バックエンド(Controller)

コード全文

src/Controller/UsersController.php

namespace App\Controller;
use Cake\Auth\DefaultPasswordHasher;
・・・その他読み込み

class UsersController extends AppController
{

    public function changePassword(){
        $error = "";

        if ($this->request->is('post')){
            //ログイン済みのユーザセッション情報
            $user = $this->request->getAttribute('identity');
            //現パスワード
            $password = $this->request->getData('password');
            //新パスワード
            $newPassword = $this->request->getData('new-password');
            //元パスワードの一致チェック用hasher
            $hasher = new DefaultPasswordHasher();

            //現パスワードとログイン済ユーザのパスワードを照合する。
            if ($hasher->check($password, $user->password)) {
                //更新のために該当ユーザの情報をDBから再取得
                $userEntity = $this->Users->find()->where(["id" => $user->id])->first();
                //パスワードを更新
                $userEntity->password = $newPassword;
                //ユーザ情報を保存する
                if($this->Users->save($userEntity)){
                    //ユーザ情報を更新したので、セッションを書き換える
                    $this->Authentication->setIdentity($userEntity);
                    $error = "更新に成功しました";
                }else{
                    $error = "更新に失敗しました";
                }
            }else{
                $error="現在のパスワードが不一致でした";
            }

        }


        $this->set(compact('error'));
    }

}

コード解説

8~13行目:Post情報、ユーザ情報を取得する

ログイン済みユーザのセッション情報、フォームから送信されたPOST情報を取得しています。

//ログイン済みのユーザセッション情報
$user = $this->request->getAttribute('identity');
//現パスワード(POST情報1)
$password = $this->request->getData('password');
//新パスワード(POST情報2)
$newPassword = $this->request->getData('new-password');
18~22行目、35~37行目:パスワードを照合する

「フォームで入力した現在のパスワード」と「ログイン済みユーザ情報」のパスワードを照合しています。

不一致であれば、その旨エラーを返します($error)。

//元パスワードの一致チェック用hasher
$hasher = new DefaultPasswordHasher();
//現パスワードと新パスワードを照合する。
if ($hasher->check($password, $user->password)) {
  ・・・・・
}else{
     $error="現在のパスワードが不一致でした";
}
23~26行目:ログイン済みユーザのUserEntityに新パスワードをセットする。

先ほどのコードでフォームで入力した「現在のパスワードの一致」はチェックできました。

更新用にログイン済みユーザのユーザエンティティーを取得し、パスワード情報をセットします。

//更新のために該当ユーザの情報をDBから再取得
$userEntity = $this->Users->find()->where(["id" => $user->id])->first();
//パスワードを更新
$userEntity->password = $newPassword;

※パスワードのハッシュ化について

新パスワードのセット時に「パスワードをハッシュ化(暗号化)しなくてもいいの?」と思われるかもしれません。

しかし、公式の「シンプルな認証と認可のアプリケーション」を参考に、普通にログイン認証ロジックを作っていれば、Usersのパスワード更新時に自動でハッシュ化されます。

src/Model/Entity/user.php

protected function _setPassword($password)
    {
        if (strlen($password) > 0) {
            return (new DefaultPasswordHasher)->hash($password);
        }
    }
27~34・42行目

ユーザ情報をDBに保存します。

また、ユーザ情報を更新したので、ログインユーザセッションの情報を更新します。

更新に成功したか否かをフォームに返して表示させます。

//ユーザ情報を保存する
if($this->Users->save($userEntity)){
     //ユーザ情報を更新したので、セッションを書き換える
     $this->Authentication->setIdentity($userEntity);
     $error = "更新に成功しました";
}else{
    $error = "更新に失敗しました";
}

・・・
//フォームに保存の結果を返す。成功?失敗?
$this->set(compact('error'));

まとめ・所感

ウェブサービス運用時に、パスワード更新機能の重要度はかなり高いです。

しかし、CakePHP4・Authenticationのパスワード更新フォームに関する記事はなかなか発見できませんでした。

公式を確認しつつ、ひとつひとつ機能を組み合わせていったところ、無事に問題なく稼働するパスワード更新フォームをつくることができました。

コメント

タイトルとURLをコピーしました