データベースからYii2のユーザ認証を行う

Yii2

Yii2は、初期の状態でユーザ認証のデモがありますが、ユーザーデータはモデルに直接記載された配列のデータを参照するものになります。

ここでは初期のユーザ認証のデータ参照先をデータベースへ切り替える方法について説明します。

プロジェクトの準備

プロジェクトの作成

Yii2のプロジェクトを作成します。

$ cd /var/www/html
$ composer create-project --prefer-dist yiisoft/yii2-app-basic example

データベースの設定

config/db.phpを編集してデータベースの接続情報を編集します。

config/db.php
return [
    'class' => 'yii\db\Connection',
    'dsn' => 'mysql:host=localhost;dbname=<データベース名>',
    'username' => '<ユーザ名>',
    'password' => '<パスワード>',
    'charset' => 'utf8',

Gii (コードジェネレーター)の有効化

Yii2のCRUD生成ツールであるGiiが利用できるようconfig/web.phpを編集します。

config/web.php
・・・省略
    $config['bootstrap'][] = 'gii';
    $config['modules']['gii'] = [
        'class' => 'yii\gii\Module',
        // uncomment the following to add your IP if you are not connecting from localhost.
        'allowedIPs' => ['<アクセス元IPアドレス>'],
    ];
・・・省略

マイグレーションの用意

データベース管理ツールを使うことで簡単な定義分から構造であるスキーマを生成することができます。

$ yii migrate

これでプロジェクトの準備は整いました。

ユーザの参照先データの移行

userテーブルの作成

以下のコマンドでuserテーブルのスキーマーをマイグレーションで生成します。

$ yii migrate/create create_user_table --fields="username:string(32):notNull,password:string:notNull,access_token:string,auth_key:string(32),created_at:dateTime,updated_at:dateTime"
Yii Migration Tool (based on Yii v2.0.29)
Create new migration '/var/www/html/example/migrations/m191031_095033_create_user_table.php'? (yes|no) [no] Yes
New migration created successfully.

次のコマンドでuserテーブルの構造をデータベースへ反映します。

$  php yii migrate/up
Yii Migration Tool (based on Yii v2.0.29)

Total 1 new migration to be applied:
        m191031_095431_create_user_table

Apply the above migration? (yes|no) [no]:yes
*** applying m191031_095431_create_user_table
    > create table {{%user}} ... done (time: 0.032s)
*** applied m191031_095431_create_user_table (time: 0.102s)


1 migration was applied.

Migrated up successfully.

新しいUserモデルの作成

Yii2では初期の状態でモデルに直接定義されたデータを参照する為のUserモデルが存在します。

今回はデータベースへ参照する為に作成し直すので、ファイル名を変更します。

$ cd models
$ mv User.php User.php.org

次にGiiのコードジェネレータを使ってUserモデルを生成します。

Table Nameuser
Model Class NameUser

Userモデルの編集

認証モジュールの追加

以下のように認証モジュールを追加し、Userモデルが連携できるようにします。

・・・省略
namespace app\models;

use Yii;
use yii\web\IdentityInterface; // 追加

・・・省略

class User extends \yii\db\ActiveRecord implements IdentityInterface // implements で連携させる
{
・・・省略

次に認証時に必要な以下のメソッドを追加します。

メソッド追加:findIdentity

    public static function findIdentity($id)
    {
        return static::findOne($id);
    }

メソッド追加:findIdentityByAccessToken

    public static function findIdentityByAccessToken($token, $type = null)
    {
        return static::findOne(['access_token' => $token]);
    }

メソッド追加:findByUsername

    public static function findByUsername($username)
    {
        return static::findOne(['username' => $username]);
    }

メソッド追加:getId

    public function getId()
    {
        return $this->id;
    }

メソッド追加:getAuthKey

    public function getAuthKey()
    {
        return $this->auth_key;
    }

メソッド追加:validateAuthKey

    public function validateAuthKey($authKey)
    {
        return $this->getAuthKey() === $authKey;
    }

メソッド追加:validatePassword

    public function validatePassword($password)
    {
        return Yii::$app->security->validatePassword($password, $this->password);
    }

次に新規ユーザ登録時にauth_keyを設定するように処理を追加します。

以上で完了となりますが、このままではユーザ情報がデータベースに入っていないので、確認できませんので、次にユーザの登録・更新・削除ができる環境をGiiを使って構築します。

Userの登録編集機能の構築

Gii の CRUD GeneratorでUserテーブルへアクセスしてデータの登録・更新・削除ができる機能を生成します。

Model Classapp\models\User
Search Model Classapp\models\UserSearch
Controller Class View Pathapp\controllers\UserController
View Path@app\views\user
その他 Enable Pjax のみチェック

生成されたかブラウザから確認します。

http://example.com/index.php?r=user%2Findex

登録画面も見てみます。

登録画面では、UsernameとPasswordの項目が必要ですがこれ以外の入力項目は必要ありませんので、ビューファイルを編集します。

views/user/_form.php
・・・省略
    <?= $form->field($model, 'username')->textInput(['maxlength' => true]) ?>

    <?= $form->field($model, 'password')->passwordInput(['maxlength' => true]) ?>
<!-- ここから -->
    <?= $form->field($model, 'access_token')->textInput(['maxlength' => true]) ?>
      
    <?= $form->field($model, 'auth_key')->textInput(['maxlength' => true]) ?>

    <?= $form->field($model, 'created_at')->textInput() ?>

    <?= $form->field($model, 'updated_at')->textInput() ?>
<!-- ここまでを削除 -->

・・・省略

登録、更新(created_at, updated_at)の処理

データは追加された場合はcreated_at、更新された場合はupdated_atのカラムへタイムスタンプが登録されるように処理を追加します。

use を2つ追加及びbehaviorsのメソッドを追加します。

models\User.php
・・・省略
use Yii;
use yii\behaviors\TimestampBehavior; // 追加
use yii\db\Expression; // 追加
use yii\web\IdentityInterface;
・・・省略
    // 以下のメソッドを追加
    public function behaviors()
    {
      return [
        [
          'class' => TimestampBehavior::className(),
          'createdAtAttribute' => 'created_at',
          'updatedAtAttribute' => 'updated_at',
          'value' => new Expression('NOW()'),
        ],
      ];
    }
・・・省略

これでユーザの登録と更新を試してみます。

created_at及びupdated_atが正常に動作しているのが確認できますが、パスワードが平文のまま保存されている為、セキュリティー上危険な状態ですので、復号不能なハッシュ値で保存するように変更します。

パスワードをハッシュ値に変換

この処理はデータを保存する直前に変換する必要がありますので、UserモデルのbeforeSaveメソッドを以下のように編集します。

models/User.php
・・・省略
    public function beforeSave($insert)
    {
      if (parent::beforeSave($insert)) {
        if ($this->isNewRecord) {
          $this->auth_key = Yii::$app->security->generateRandomString();
        }
    // 以下を追加
        $this->password = Yii::$app->security->generatePasswordHash($this->password);
        return true;
      }
      return false;
    }
・・・省略

これで登録したユーザデータを更新しパスワードをハッシュ化した値が保存されている事が確認できます。

ログイン確認

次にログインしてみます。

正常にログインができました。

これで完了です。

コメント

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