Laravel4、簡単なユーザー認証のサンプル

Tags : Laravel4  

Laravel4も段々認知されてきたようです。

ユーザー認証まで行う、シンプルなサンプルを紹介しましょう。順番に説明しますので、内容は簡単ですが、基本的な部分は身につきます。

まずは、新しいLaravel4の環境を用意してください。当サイトを含め、いろいろなサイトで紹介されています。皆さんの環境に一番合う情報源を参照してください。

インストール後、必要な設定を行なってください。今回のチュートリアルでは、アプリケーションキーの設定だけ、行なってあれば良いでしょう。

データベースの準備

Laravelの標準的な認証には、データベースのテーブルが、ユーザー情報の保存に使用されます。デフォルトで、"users"という名前になります。

今回のチュートリアルでは一番、利用頻度が高いと思われるMySQLを使用します。他のDBシステムを使う場合でも、以下の設定以外は共通に使用できるかと思います。

まず必要なのは、データベースです。データベースはPHPMyAdminなどのGUIツールを使用するか、MySQLのコマンドラインから作成してください。今回はDB名を"japan"にしました。

続いて、データベース設定ファイルを開いてください。app/config/database.phpです。該当部分を以下のように設定してください。テーブル名、MySQLユーザー名、パスワードは、ご自身の設定に合わせてください。

'mysql' => array(
    'driver'    => 'mysql',
    'host'      => 'localhost',
    'database'  => 'japan', // データベース名
    'username'  => 'root',  // MySQLユーザー名
    'password'  => 'root',  // パスワード
    'charset'   => 'utf8',
    'collation' => 'utf8_unicode_ci',
    'prefix'    => '',
),

ユーザーテーブルの準備

テーブルの作成は、マイグレーションで行いましょう。

まず、Artisanコマンドラインで、対象のファイルを作成します。

php artisan migrate:make CreateUserTable

このコマンドにより、app/database/migrationsディレクトリー下に、ファイルが生成されます。ファイル名の最後が"_CreateUserTable.php"になっており、名前の頭は生成日時になっています。

そのファイルを開き、以下のように設定してください。

<?php

use Illuminate\Database\Migrations\Migration;

class CreateUsersTable extends Migration
{

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        if( !Schema::hasTable( 'users' ) )
        {
            Schema::create( 'users', function($table)
                {
                    $table->increments( 'id' );
                    $table->string( 'username', 20 );
                    $table->string( 'password', 64 );
                    $table->timestamps();
                } );
        }
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists( 'users' );
    }

}

この設定内容に従い、マイグレーションを実行し、テーブルを生成します。

php artisan migrate

Userモデルの調整

Laravel4をインストールすると、初めからある程度設定された、Userモデルファイルがapp/modelsに用意されています。User.phpファイルを開いてください。

今回は、このデフォルトのまま使用するので、変更する必要はありません。ただ、パスワードをセットするたびに、ハッシュをかけるのは面倒なので、セッターで指定してしまいましょう。以下のメソッドを追加してください。

    public function setPasswordAttribute($value)
    {
        $this->attributes['password'] = Hash::make($value);
    }

テストUserの準備

動作確認のための、ダミーユーザーを用意します。

Laravel4から導入された、DBのシーディングを使用します。これは、テーブルへ初期値を設定することです。

まずは、シーディングのコントロールを行う、app/database/seeds/DatabaseSeeder.phpを開いてください。以下のように、一行のコメントを外します。

        $this->call('UserTableSeeder');

この行が表すのは、UserTableSeederクラスのrunメソッドを実行しろという意味です。シーディングに使用するクラスには、シーディングのコードを含んだ、runメソッドを用意して置きます。

app/database/seeds/UserTableSeeder.phpを作成し、以下のようにダミーユーザーの生成コードを用意します。

<?php

class UserTableSeeder extends Seeder
{
    public function run()
    {
        DB::table( 'users' )->delete();

        User::create( array(
            'username' => 'test',
            'password' => 'test'
        ) );
    }

}

ユーザー名、パスワード共に"test"のユーザーです。パスワードを平文で渡していますが、先程のUserモデルの設定により、この様にフィールドをセットするだけで、ハッシュされ、保存されます。

では、シーディングを実行しましょう。

php artisan db:seed

このコマンドで、DatabaseSeederクラスのrunメソッドが実行されます。その中から、UserTableSeederが呼び出され、ユーザー情報が追加されます。

もし直接、UserTabelSeederを呼び出したい場合は、コマンドでクラス名を指定することにより、特定のSeederクラスを実行できます。

ルートの指定

今回は、シンプルに説明するために、app/routes.phpに全ルートを記述します。こうした、簡単な実験には、クロージャーによるルーティングの指定は、本当に便利です。

<?php

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

Route::when( 'protect*', 'auth' );

Route::get( '/protect1', array( function()
    {
        return '秘密のページ1';
    } ) );

Route::get( 'protect2', array( function()
    {
        return '秘密のページ2';
    } ) );

Route::get( 'login', function()
    {
        return View::make( 'login' );
    } );
Route::post( 'login', function()
    {
        // バリデーション省略

        if( Auth::attempt( Input::only('username', 'password')) )
        {
            return Redirect::intended( '/' );
        }
        return Redirect::back()->withInput();
    } );

Route::get( 'logout', function()
    {
        Auth::logout();
        return Redirect::to( '/' );
    } );

"/protect1"と"/protect2"が、認証で保護されているページです。認証のための"Auth"フィルターをURIが"/protect"で始まる全ページに指定しています。

ログインフォームをGETメソッドの"/login"で表示し、POSTで返ってきたレスポンスにて、フォームの入力内容をログイン情報として処理しています。

シンプルにするため、CSRFフィルターや、フォームのバリデーションは省略しています。

Auth::attempt()で認証の判断をしています。passwordはパスワードとして必須ですが、その他の項目はどれでも構いません。一意のフィールドを一つ以上指定するか、もしくは、組み合わせて一意となるフイールドを指定します。通常は、ユーザー名か、パスワードのどちらかになると思います。

認証フィルター

app/filters.phpを開いてください。ルーティングのためのフィルターを記述するファイルです。認証フィルターを確認してください。デフォルトのままで構いません。変更する必要はありません。

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

フィルターにはどのリクエストでも実行されるものと、ルートに対して指定するものがあります。さらに、リクエストの前に実行するもの、後に実行するものに湧かれますので、計4種類あると考えてください。

この、authフィルターは、指定したURIに対して実行する、リクエスト前に通されるフィルターです。こうしたリクエスト前に実行される、Beforeフィルターの中から、適当な値がリターンされると、そのルートの実行は中止され、リターンされた内容がリクエストに対する、レスポンスになります。

今回の場合、Auth::guest()で、ゲスト状態、つまり未ログインかを確認しています。未ログインの場合は、Redirect::guest('login')がリターンされ、これが実行されます。

つまり、未ログインの状態で、"/protect1"、"/protect2"にログインすると、guestメソッドに指定されたURI、この場合は"/login"にリダイレクトされるわけです。

通常、特定のURIに対するリダイレクトは、Redirect::to()を使用します。guestメソッドは、認証フィルターのためのメソッドで、アクセスされたURIをセッションに保存してから、指定先のURIへリダイレクトします。

通常は、ログインページです。そこで、認証のルートを見てください。認証処理では、成功時にRedirect::intended( '/' )を使用しています。この、intendedメソッドは、まずセッションにguestメソッドにより保存されたURIの存在を確認します。

URIが保存されていた場合、そのURIへリダイレクトします。URIが保存されていない場合、保存していてもリダイレクトが無効な場合は、メソッドに指定されたURIへリダイレクトします。今回はルート('/')にリダイレクトします。(試して見るためには、"/login"にアクセスし、ログインしてください。ルートへリダイレクトされます。)

つまり、ユーザーが、"protect1"ヘ未ログインの状態でアクセスすると、ログインページへリダイレクトします。そこで正しいログイン情報を入力すると、認証され、"protect1"ページの内容が表示されるわけです。最初のアクセスが"protect2"の場合なら、当然ログイン後に、"protect2"へリダイレクトされます。

ビュー

最後に、ビューを紹介します。app/views/login.blade.phpです。

{{ Form::open() }}
{{ Form::label('username', 'ユーザー名:') }}
{{ Form::text('username', Input::old('username', '')) }}
<br>
{{ Form::label('password', 'パスワード:') }}
{{ Form::password('password') }}
<br>
{{ Form::submit('ログイン'); }}
{{ Form::close() }}