Laravel

Laravel3 データベースを使わない簡易認証

CakePHP以外のフレームワークを、と思っていくつか手を出したけど利用するところまで到達できない状態でした。ですがLaravelを習い始めてみると何となくイケそうな気がします。で、折角ですので備忘録も兼ねてブログに残そうかと思います。

Laravelの取り付きには、川瀬さんが翻訳されて出版されている電子書籍 Code Happy(JP) が良いかと思います。このネタもCode Happyの説明を利用したものです。以下「である調」で記述します。

小さなWebアプリで認証管理にユーザー登録機能を用意するのは、大した作業ではないが管理画面の処理も用意しなければならないので面倒だ。管理者1,2人程度ならプログラムに埋め込んで認証できればお手軽で良い。Laravelでは、認証の仕組みを利用して簡単に実現できた。

先ずは動きを見るための、外堀のプログラムから。

サイトのURLを「http://www.example.com」とし、「http://www.example.com/home」はログインユーザーのみ公開されているとする。ログインしていない状態で「home」を表示しようとするとログイン画面にリダイレクトされる。

LaravelはフレームワークなのでMVCのアプリケーションを組めるが、routes.php を利用してRESTfulなアプリケーションが組めるようになっており、オートロードの機能もありクラスを柔軟に活用できる。

home をアクセスしたとき homeビューを表示するプログラムは次の通り。

application/routes.php

Route::get('home', function() {
    return View::make('home');
});

簡単な homeビューを用意する。

application/views/home.blade.php

<div class="header">
    ようこそ!<br />
    {{ HTML::link('logout', 'ログアウト') }}
</div>
<div class="content">
    <h1>管理画面トップ</h1>
    <p>データベースを使わない簡易認証のページです。</p>
</div>

これだけで home にアクセスするとビューが表示される。

次はログインフォームのビュー。

application/views/login.blade.php

{{ Form::open('login') }}
    @if (Session::has('login_errors'))
        <span class="error">ログインエラー</span>
    @endif
    <p>{{ Form::label('username', 'ユーザー名:') }}
       {{ Form::text('username') }}</p>
    <p>{{ Form::label('password', 'パスワード:') }}
       {{ Form::password', 'パスワード' }}</p>
    <p>{{ Form::submit('ログイン') }}</p>
{{ Form::close() }}

で、ログイン画面の表示と送信されたログインデータを処理するプログラムの用意。どちらも routes.php 内で動作するように以下を追加。

application/routes.php

Route::get('login', function() {
    return View::make('Login');
});

Route::post('login', function() {
    return 'ログイン送信';
});

とりあえず、「http://www.example.com/login」でログインフォームの表示を確認し、ログインボタンを押すと「ログイン送信」が表示されるか確認する。

次に、home がアクセスされた時ログインチェックをして未ログインならログインフォームへ移行するようにする。これは、「Route::get(‘home’, …」で、処理をする前に認証チェックのフィルタプログラムを実行するように、次のように書き換える。

application/routes.php

Route::get('home', array('before' => 'auth', 'do' => function() {
    return View::make('home');
}));

そしてフィルタ「auth」をroutes.phpに追加する。が、「auth」フィルタは通常次のように routes.php に組み込まれている。

application/routes.php

Route::filter('auth', function()
{
    if (Auth::guest()) return Redirect::to('login');
}));

Auth::guest() はログインされていなければ true を戻す。Auth::check() はログインされていると true を戻す。

では、http://www.example.com/home へアクセスするとリダイレクトするか確認する。

いよいよLaravelの認証の仕組みを利用して簡易認証する手順に入る。

簡易認証のプログラムの内容は簡単で、usernameとpasswordを受け取り、プログラム内に書き込んだユーザー名とパスワードに一致するかどうかを判定するだけだ。なお、Laravelの仕組みに合わせるため認証プログラムは「Laravel\Auth\Drivers\Driver」から派生させ、認証メソッド「attempt()」とログインユーザーデータを戻すメソッド「retrieve()」を準備する。ファイルは「application/libraries/myauth.php」とする。これでオートロードされる。

application/libraries/myauth.php

<?php
class Myauth extends Laravel\Auth\Drivers\Driver
{
    private static $auth_users = array(
        array('id' => 1, 'username' => 'admin', 'password' => 'admin',
        array('id' => 2, 'username' => 'root', 'password' => 'root',
    );

    public function attempt($arguments = array())
    {
        $username = $arguments['username'];
        $password = $arguments['password'];

        foreach (self::$auth_users as $user) {
            if ($user['username'] == $username)
             && $user['password'] == $password) {
                return $this->login($user['id'],
                    array_get($arguments, 'remember'));
            }
        }

        return false;
    }

    public function retrieve($id)
    {
        foreach (self::$auth_users as $user) {
            if ($user['id'] == $id) {
                $data = new stdClass();
                $data->id = $user['id'];
                $data->username = $user['username'];
                $data->password = $user['password'];
                return $data;
            }
        }

        return null;
    }
}

Laravelで認証をどのように実行するかについての設定が「application/config/auth.php」にある。この中で、myauthを利用する設定とデータのusernameの項目名が何かの設定の2つ、変更しなければならない。

application/config/auth.php

'dirver' => 'myauth',
'username' => 'username',

そしてこれを使用することをAuthクラスに登録するため、「application/start.php」に次のように追加する(ファイルの最後に追加)。

Auth::extend('myauth', function() {
    return new Myauth();
});

ところで、ログインデータが送信されたときこのプログラムでユーザーを確認し、認証がOKならhomeへリダイレクトし、認証が失敗した場合はログイン画面へ戻るようにする部分を先の「Route::post(‘login’,…」に組み込む。合わせてログアウトするとログイン画面へリダイレクトする機能も実装する。いずれも routes.php 上である。

application/routes.php

Route::post('login', function() {
    $userdata = array(
        'username' => Input::get('username'),
        'password' => Input::get('password'),
    );

    if (Auth::attempt($userdata)) {
        return Redirect::to('home');
    }

    return Redirect::to('login')
        ->with('login_errors', true);
});

Route::get('logout', function() {
    Auth::logout();
    return Reidrect::to('login');
});

最後に、実際にログインして表示できた時「ようこそ、xxさん!」と表示するように、home.blade.phpビューを次のように変更しておく。

application/views/home.blade.php

:
ようこそ、{{ Auth::user()->username }}さん!<br />
:

動作するのを見て、Laravel 使いやすいな、と思った。

ところで、「application/config/session.php」にセッションデータのソースを操作するドライバの指定がある。この中で「’driver’ => ‘cookie’,」となっている部分を「’driver’ => ‘file’,」に変更するとセッションデータが、「storage/sessions」に書き込まれるようになる。