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() }}