CakePHP Authコンポーネントを使ってみた

CakePHP1.3系のAuthコンポーネントを使ってみました。
簡単に実装できる認証システムなので、僕自身の復習も兼ねて実装方法を紹介しようと思います。


まずは、テーブルを作成します。
Authコンポーネントは、デフォルトの状態だと『users』というテーブルを使用します。
『users』テーブルには、『username』と『password』を作成しないといけません。
注意点は、ログインパスワードはデフォルトの状態だと『sha1』でハッシュ化されるので『password』には最低でも40文字以上は保存できるようにすることぐらいです。
(使用するテーブル名やカラム名を指定する事もできるので、違う名前をつけてもかまいません。ハッシュ関数を『sha1』以外を使用したい場合は、使用したいハッシュ関数に合わせて『password』の長さを変更してください。)

▼『users』テーブルを作成するSQLの例

CREATE TABLE tests (
    id INT auto_increment,
    username VARCHAR(50),
    password VARCHAR(70),
    PRIMARY KEY(id)
)

『users』テーブルを作成するSQLはこんな感じでいいと思います。


テーブルの準備が終わったら、次はコントローラーの準備です。
モデル名に合わせて『UsersController』を作成します。
Authコンポーネントを使用するので、メンバ変数『$components』に”Auth”を渡します。

▼『users_controller.php』の例

class UsersController extends AppController {
    public $name       = 'Users';
    public $components = array('Auth');

    // ログイン処理
    // Authコンポーネントが処理してくれるので空でオッケー
    public function login() {
    }

    // ログアウト処理
    public function logout() {
        $this->Auth->logout();
    }
}

先程パスワードは『sha1』で暗号化されると言いましたが、使用するハッシュ関数を変更することもできます。
変更する場合は、

Security::setHash(使用するハッシュ関数)

を使用します。

CakePHP1.3系でサポートしているハッシュは、「md5」「sha1」「sha256」なので「sha256」を使用したい場合は

Security::setHash(‘sha256’)

という感じです。

また、この状態では全てのアクションに対して認証が適用されてしまいます。
認証を行わないアクションがでてくる場合もありますよね。
『UsersController』の場合は、『login』や『logout』などです。
認証を行わないアクションを指定するには、

$this->Auth->allow(認証を行わないアクション)

を使用します。

『login』で認証を行わない場合は、

$this->Auth->allow(‘login’)

という感じになります。

最低限な認証に使用するアクションは『login』と『logout』ぐらいだと思いますが、初めてAuthコンポーネントを使用する場合は、まだユーザーを登録していないので誰もログインすることができません。
それだと困ってしまうので、最初だけ『UsersController』にユーザー登録のアクションも作っておきます。
修正した『UsersController』は、以下のようになります。

▼『users_controller.php』を修正した例

class UsersController extends AppController {
    public $name       = 'Users';
    public $components = array('Auth');

    // 認証処理が行われる前の処理
    public function beforeFilter() {
        // ハッシュ関数を『sha1』から『sha256』に変更
        Security::setHash('sha256');

        // ログインアクションとログアウトアクションは認証しない
        $this->Auth->allow('login');
        $this->Auth->allow('logout');
        $this->Auth->allow('add');
    }

    // ログイン処理
    // Authコンポーネントが処理してくれるので空でオッケー
    public function login() {
    }

    // ログアウト処理
    public function logout() {
        $this->Auth->logout();
    }

    // ユーザー登録
    public function add() {
        if(!empty($this->data)) {
            // メンバー追加
            $this->User->create();
            $this->User->save($this->data['User']);

            // リダイレクト
            $this->redirect('./login');
        }
    }
}

Authコンポーネントで使用するテーブル名を変更した方は、

$this->Auth->userModel = ‘テーブル名’

でメンバ変数を変更してください。

Authコンポーネントで使用するカラム名を変更した方は、

$this->Auth->fields = array(‘username’ => ‘ユーザー名のカラム名’, ‘password’ => ‘パスワードのカラム名’)

でメンバ変数を変更してください。


コントローラーの作成ができたら、『login』ビュー・『logout』ビュー・『add』ビューを作成します。

『login』ビューには『username』と『password』を入力できるフィールドを用意します。

▼『login.ctp』の例

if ($session->check('Message.auth')) echo $session->flash('auth');
echo $form->create('User', array('action' => './login'));
echo $form->input('username');
echo $form->input('password');
echo $form->end('ログイン');

1行目の『if ($session->check(‘Message.auth’))』でログインエラーテキストなどがあるか判別し、テキストがあれば『echo $session->flash(‘auth’)』でテキストを表示しています。
残りはログインフォームを作ってるだけです。
『logout』ビューは、ログアウトした旨を伝える文章などを書いておけばいいと思います。

▼『loout.ctp』の例

<p>ログアウトしました。</p>

『add』ビューには、『username』と『password』を入力するフィールドを用意します。

▼『add.ctp』の例

echo $form->create('User', array('type'=>'post', 'action'=>'./add'));
echo $form->input('username');
echo $form->input('password');
echo $form->end('ユーザー追加');

これでAuthコンポーネントを使用する準備は完了しました。
試しに、CakePHPのトップページのコントローラー『pages_controller.php』にAuthコンポーネントを使用してみます。
予め、『add』アクションでユーザーを登録しておき、登録が完了したらアクションを削除するか、認証を行うようにしておいてください。
(『pages_controller.php』の説明などは「CakePHP そういえば、トップページのコントローラーは?」を参照。)

▼『pages_controller.php』でAuthコンポーネントを使用する例

class PagesController extends AppController {
    public $name       = 'Pages';
    public $uses       = null;
    public $components = array('Auth');

    public function display() {
    }
}

メンバ変数『$components』に”Auth”を渡し、Authコンポーネントを使用できるようにします。
この状態でトップページにアクセスしてみると、自動的にログインページに飛ばされます。
ログインに成功すると、アクセスしようとしていたページに。ログインに失敗すると、ログインに成功するまでログインページを表示してくれます。
ログインしていない場合のメッセージや、ログインに失敗した場合のエラーメッセージを変更したい場合は、

$this->Auth->authError = ‘ログインしていない場合のメッセージ’
$this->Auth->loginError = ‘ログインに失敗した場合のメッセージ’

でメンバ変数を変更します。

▼『pages_controller.php』でエラーメッセージを変更する例

class PagesController extends AppController {
    public $name       = 'Pages';
    public $uses       = null;
    public $components = array('Auth');

    public function beforeFilter() {
        $this->Auth->authError = 'ログインしてください';
    }

    public function display() {
    }
}

▼『users_controller.php』でエラーメッセージを変更する例

class UsersController extends AppController {
    public $name       = 'Users';
    public $components = array('Auth');

    // 認証処理が行われる前の処理
    public function beforeFilter() {
        // ハッシュ関数を『sha1』から『sha256』に変更
        Security::setHash('sha256');

        // ログインアクションとログアウトアクションは認証しない
        $this->Auth->allow('login');
        $this->Auth->allow('logout');

        // ログインエラーメッセージ
        $this->Auth->authError  = 'ログインしてください';
        $this->Auth->loginError = 'ログインに失敗しました。ユーザー名かパスワードが間違っています。';
    }

    // ログイン処理
    // Authコンポーネントが処理してくれるので空でオッケー
    public function login() {
    }

    // ログアウト処理
    public function logout() {
        $this->Auth->logout();
    }
}

ログイン後のリダイレクト先は、ログインする前にアクセスしようとした場所ですが、『loginRedirect』でリダイレクト先を指定することができます。

$this->Auth->loginRedirect = array(‘controller’ => ‘コントローラー名’, ‘action’ => ‘アクション名’);

ログイン処理を行う場所を変更する場合は、『loginAction』を変更します。

$this->Auth->loginAction = array(‘controller’ => ‘コントローラー名’, ‘action’ => ‘アクション名’);

ログアウト後のリダイレクト先を指定する場合は、『logoutAction』を変更します。

$this->Auth->logoutRedirect = array(‘controller’ => ‘users’, ‘action’ => ‘login’);

僕の実装方法がおかしいのかもしれませんが、僕の環境ではリダイレクトしてくれませんでした・・・
CakePHP1.3マニュアルを読んでいたら「Auth の logout メソッドは基本的に Auth Session キーを削除し、リダイレクトすべき URL を返す。」とあったので、『logoutRedirect 』でリダイレクト先を指定し、戻り値を使ってリダイレクトするっぽいです。
それなので、UserControllerのlogoutアクションで

$this->redirect($this->Auth->logout())

としてリダイレクトさせています。


最低限の認証システムは、これで完成です。
1から自分で組むのを考えると、とても楽ですね。
フレームワーク最高!!