0 フォロワー

ユーザー認証

当ブログアプリケーションでは、システムオーナーとゲストユーザーを区別する必要があります。そのため、ユーザー認証機能を実装する必要があります。

スケルトンアプリケーションは、既にユーザー名とパスワードが両方ともdemoまたはadminであるかどうかをチェックすることでユーザー認証を提供していることに気付いているかもしれません。このセクションでは、認証がUserデータベーステーブルに対して行われるように、対応するコードを変更します。

IUserIdentityインターフェースを実装するクラスでユーザー認証が行われます。スケルトンアプリケーションでは、この目的のためにUserIdentityクラスを使用しています。このクラスは、/wwwroot/blog/protected/components/UserIdentity.phpファイルに格納されています。

ヒント:慣例により、クラスファイルの名前は、対応するクラス名に拡張子.phpを付けたものにする必要があります。この慣例に従うことで、パスエイリアスを使用してクラスを参照できます。たとえば、UserIdentityクラスはapplication.components.UserIdentityエイリアスで参照できます。Yiiの多くのAPIはパスエイリアスを認識でき(例:Yii::createComponent())、パスエイリアスを使用すると、コードに絶対ファイルパスを埋め込む必要がなくなります。後者の存在は、アプリケーションをデプロイする際にしばしば問題を引き起こします。

UserIdentityクラスを次のように変更します。

<?php
class UserIdentity extends CUserIdentity
{
    private $_id;
 
    public function authenticate()
    {
        $username=strtolower($this->username);
        $user=User::model()->find('LOWER(username)=?',array($username));
        if($user===null)
            $this->errorCode=self::ERROR_USERNAME_INVALID;
        else if(!$user->validatePassword($this->password))
            $this->errorCode=self::ERROR_PASSWORD_INVALID;
        else
        {
            $this->_id=$user->id;
            $this->username=$user->username;
            $this->errorCode=self::ERROR_NONE;
        }
        return $this->errorCode==self::ERROR_NONE;
    }
 
    public function getId()
    {
        return $this->_id;
    }
}

authenticate()メソッドでは、Userクラスを使用して、username列が与えられたユーザー名と同じ(大文字と小文字を区別しない)tbl_userテーブルの行を探します。Userクラスは、前のセクションでgiiツールを使用して作成されたことを思い出してください。UserクラスはCActiveRecordを継承しているため、ActiveRecord機能を利用して、OOP形式でtbl_userテーブルにアクセスできます。

ユーザーが有効なパスワードを入力したかどうかを確認するために、UserクラスのvalidatePasswordメソッドを呼び出します。/wwwroot/blog/protected/models/User.phpファイルを次のように変更する必要があります。データベースにプレーンテキストのパスワードを保存する代わりに、パスワードのハッシュを保存することに注意してください。ユーザーが入力したパスワードを検証する際には、代わりにハッシュ結果を比較する必要があります。Yii組み込みのCPasswordHelperを使用して、パスワードをハッシュし、検証します。

class User extends CActiveRecord
{
    ......
    public function validatePassword($password)
    {
        return CPasswordHelper::verifyPassword($password,$this->password);
    }
 
    public function hashPassword($password)
    {
        return CPasswordHelper::hashPassword($password);
    }
}

UserIdentityクラスでは、tbl_userテーブルで見つかったユーザーのid値を返すgetId()メソッドもオーバーライドしています。親の実装では、代わりにユーザー名が返されます。usernameプロパティとidプロパティの両方がユーザーセッションに保存され、コード内の任意の場所からYii::app()->userを介してアクセスできます。

ヒント:UserIdentityクラスでは、対応するクラスファイルを明示的にインクルードすることなく、CUserIdentityクラスを参照しています。これは、CUserIdentityがYiiフレームワークによって提供されるコアクラスであるためです。Yiiは、コアクラスが初めて参照されたときに、そのクラスファイルが自動的にインクルードされます。

Userクラスでも同じことを行います。これは、Userクラスファイルが/wwwroot/blog/protected/modelsディレクトリに配置されており、アプリケーション設定にある次の行に従ってPHPのinclude_pathに追加されているためです。

return array(
    ......
    'import'=>array(
        'application.models.*',
        'application.components.*',
    ),
    ......
);

上記の構成は、クラスファイルが/wwwroot/blog/protected/modelsまたは/wwwroot/blog/protected/componentsのいずれかの下に位置するクラスは、クラスが初めて参照されたときに自動的にインクルードされることを示しています。

UserIdentityクラスは主に、ログインページから収集されたユーザー名とパスワードの入力に基づいてユーザーを認証するために、LoginFormクラスで使用されます。次のコードフラグメントは、UserIdentityの使用方法を示しています。

$identity=new UserIdentity($username,$password);
$identity->authenticate();
switch($identity->errorCode)
{
    case UserIdentity::ERROR_NONE:
        Yii::app()->user->login($identity);
        break;
    ......
}

情報:アイデンティティとuserアプリケーションコンポーネントについて混乱する人がよくいます。前者は認証を実行する方法を表し、後者は現在のユーザーに関連する情報を表すために使用されます。アプリケーションは1つのuserコンポーネントしか持つことができませんが、サポートする認証の種類に応じて、1つまたは複数のアイデンティティクラスを持つことができます。認証されると、アイデンティティインスタンスは状態情報をuserコンポーネントに渡すことができるため、userを介してグローバルにアクセスできます。

変更されたUserIdentityクラスをテストするには、http://www.example.com/blog/index.phpというURLにアクセスし、tbl_userテーブルに保存したユーザー名とパスワードでログインを試すことができます。ブログデモで提供されているデータベースを使用する場合は、ユーザー名demoとパスワードdemoでログインできるはずです。このブログシステムはユーザー管理機能を提供していないことに注意してください。その結果、ユーザーはWebインターフェースを介してアカウントを変更したり、新しいアカウントを作成したりすることはできません。ユーザー管理機能は、ブログアプリケーションの今後の機能強化として検討できます。

タイプミスを見つけた場合、またはこのページの改善が必要だと考える場合は?
githubで編集する !