Laravel 4.2 セキュリティー

設定

Laravelは認証をとてもシンプルに実現する目的を持っています。実際、最初から全てが設定済みです。認証の設定ファイルはapp/config/auth.phpで、認証機能の動作を調整するため、読みやすいコメントをつけた多くのオプションで構成されています。

LaravelはEloquent認証ドライバーでデフォルトとして使用されるUserモデルをapp/modelsディレクトリーに用意してあります。このモデルのスキーマを作成する場合、パスワードフィールドは最低60文字必要であることを覚えておいてください。

もし、アプリケーションでEloquentを使用しないのであれば、database認証ドライバーでクエリービルダーを使ってください。

注目: 認証を使い始める前に、users(もしくは同様の)テーブルにNULLを許す、100文字のremember_tokenカラムを確実に用意してください。このカラムはアプリケーションで"Remember me"(持続的)セッションのトークンを保存するために使用されます。マイグレーション時に、$table->rememberToken();を使用すれば作成されます。

パスワードの保存

LaravelのHashクラスは安全なBcryptハッシュを提供しています。

Bcryptを使いパスワードをハッシュする

$password = Hash::make('secret');

ハッシュに対し、パスワードを確認する

if (Hash::check('secret', $hashedPassword))
{
    // パスワード一致...
}

パスワードに再ハッシュが必要かチェックする

if (Hash::needsRehash($hashed))
{
    $hashed = Hash::make('secret');
}

ユーザー認証

あるユーザーをアプリケーションにログインさせる場合は、Auth::attemptメソッドを使います。

if (Auth::attempt(array('email' => $email, 'password' => $password)))
{
    return Redirect::intended('dashboard');
}

emailが必須のオプションでないことに注意してください。主に例を示すために使っているだけです。データベースの中にあるどんなカラム名でも"username"に該当するものを使用できます。 Redirect::intended関数は認証フィルターでキャッチされる前にアクセスしてきた、前のURLへユーザーをリダイレクトさせます。このメソッドにはフォールバックURIを指定機で、リダイレクト先へ転送できない場合に利用されます。

attemptメソッドが呼び出された時にauth.attemptイベントが発行されます。同様に、認証に成功した場合はauth.loginイベントが発行されます。

ユーザーが認証されているか判定する

ユーザーが既にアプリケーションへログインしているかをチェックするには、checkメソッドを使います。

if (Auth::check())
{
    // ユーザーはログインしている…
}

ユーザーを認証し、ログインを保つ

アプリケーションで"Remember me"機能を提供したい場合、attemptメソッドの第2引数にtrueを渡す必要があります。それにより無期限に(もしくは手動でログアウトされるまで)認証が維持されます。もちろんusersテーブルに、"Remember me"トークンを保存するために使用する、文字列のremember_tokenカラムを用意しておく必要があります。

if (Auth::attempt(array('email' => $email, 'password' => $password), true))
{
    // このユーザーは覚えられた...
}

注意:attemptメソッドがtrueを返す場合、そのユーザーはアプリケーションにログイン中だと考えられます。

ユーザーがRemember meで認証されているかを判定する

ユーザーのログインを覚えておく設定の場合、viaRememberメソッドを使用し、そのユーザーが"remember me"(ログインしたままにする)クッキーを使用して認証されているのかを判定できます。

if (Auth::viaRemember())
{
    //
}

条件付きのユーザー認証を行う

認証のクエリーに条件を追加することも可能です。

if (Auth::attempt(array('email' => $email, 'password' => $password, 'active' => 1)))
{
    // このユーザーは存在しており、アクティブで、使用停止ではない
}

注目:Session Fixation攻撃に対抗するため、認証後はセッションIDが自動的に再生成されます。

ログインしたユーザーにアクセスする

一度ユーザーが認証されると、Userモデル/レコードにアクセスできます。

$email = Auth::user()->email;

認証済みのユーザーのIDを取得するには、idメソッドを使用します。

$id = Auth::id();

アプリケーションにユーザーをIDでログインさせたい時は、loginUsingIdメソッドを使用してください。

Auth::loginUsingId(1);

ログインしないで認証内容をチェックする

validateメソッドでアプリケーションへ実際にログインさせずに、認証内容が正しいかをチェックできます。

if (Auth::validate($credentials))
{
    //
}

そのセッションの間だけユーザーをログインさせる

そのリクエスト一回の間だけユーザーをログインさせるonceメソッドも使用できます。これにはセッションもクッキーも使用されません。

if (Auth::once($credentials))
{
    //
}

アプリケーションからログアウトする

Auth::logout();

ユーザーの手動ログイン

既に存在しているユーザーをアプリケーションにログインさせる場合、そのインスタンスを指定し、loginメソッドを呼び出してください。

$user = User::find(1);

Auth::login($user);

これはユーザー情報をもとにログインさせるattemptと同じ状態になります。

ルートの保護

特定のルートへ認証済みのユーザーだけがアクセスできるように、ルートフィルターを使用できます。Laravelはデフォルトのauthフィルターをapp/filters.phpで定義しています。

ルートを保護する

Route::get('profile', array('before' => 'auth', function()
{
    // 認証済みのユーザーのみ入れる...
}));

CSRFからの保護

LaravelはCSRFからアプリケーションを簡単に守る手段を提供しています。

CSRFトークンをフォームへ埋め込む

<input type="hidden" name="_token" value="<?php echo csrf_token(); ?>">

送信されてきたCSRFトークンをバリデートする

Route::post('register', array('before' => 'csrf', function()
{
    return '有効なCSRFトークンです!';
}));

HTTP基本認証

HTTP基本認証は専用の「ログイン」ページを作成しなくても手軽にユーザーを認証できる手法です。これを使用するにはauth.basicフィルターをルートに追加してください。

HTTP基本認証でルートを保護する

Route::get('profile', array('before' => 'auth.basic', function()
{
    // 認証済みのユーザーのみ入れる...
}));

デフォルトで、basicフィルターはユーザーレコードのemailカラムを認証に使用します。ユーザーの他のカラムを使用する場合は、app/filters.phpの中で、そのカラム名をbasicメソッドの最初の引数として渡してください。

Route::filter('auth.basic', function()
{
    return Auth::basic('username');
});

ステートレスなHTTP基本フィルターをセットする

またHTTP基本認証はセッションのユーザー識別クッキーをセットせず使用することができます。これは特にAPI認証に便利です。使用するには、onceBasicメソッドをリターンするフィルターを書いてください。

Route::filter('basic.once', function()
{
    return Auth::onceBasic();
});

PHP FastCGIを使用している場合、デフォルトでHTTP基本認証は正しく動作しません。.htaccessファイルに以下の行を追加してください。

RewriteCond %{HTTP:Authorization} ^(.+)$
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

パスワードリマインダーとリセット

モデルとテーブル

ほとんどのWebアプリケーションはユーザーが忘れてしまったパスワードをリセットする手段を提供しています。それぞれのアプリケーションに毎回実装する代わりに、Laravelはパスワードリマインダーを送信し、パスワードをリセットする便利なメソッドを提供しています。最初にIlluminate\Auth\Reminders\RemindableInterfaceUserモデルへ確実に実装されていることを確認してください。もちろん、フレームワークに含まれるUserモデルには、このインターフェイスが最初から実装されています。そしてインターフェイスの実装に必要なメソッドを含んでいる、Illuminate\Auth\Reminders\RemindableTraitを使用しています。

RemindableInterfaceを実装する

use Illuminate\Auth\Reminders\RemindableTrait;
use Illuminate\Auth\Reminders\RemindableInterface;

class User extends Eloquent implements RemindableInterface {

    use RemindableTrait;

}

リマインダーテーブルのマイグレーションを生成する

次に、パスワードリセットトークンを保存するテーブルを生成します。このテーブルのマイグレーションを生成するためには、単にArtisanコマンドのauth::remindersを実行するだけです。

php artisan auth:reminders-table

php artisan migrate

パスワードリマインダーコントローラー

これでパスワードリマインダーコントローラーを生成する準備が整いました。auth:reminders-controller Artisanコマンドを使用し、コントローラーを自動的に生成しましょう。app/controllersディレクトリー中に、RemindersController.phpを生成します。

php artisan auth:reminders-controller

生成されたコントローラーには、あなたが表示したパスワードリマインダーフォームを処理する、getRemindメソッドが既に用意されています。あなたが行う必要があるのは、password.remindビューを作成することだけです。このビューはemailフィールドを持つ、基本的なフォームです。フォームはRemindersController@postRemindアクションへPOSTする必要があります。

シンプルなpassword.remindビューは以下のようになるでしょう。

<form action="{{ action('RemindersController@postRemind') }}" method="POST">
    <input type="email" name="email">
    <input type="submit" value="Send Reminder">
</form>

getRemindに加えて、生成されたコントローラーはpostRemindメソッドも持っています。これはパスワードリマインダーメールをユーザーに送信する処理を行います。このメソッドは、POST変数にemailフィールドが存在していることを期待しています。リマインダーメールがユーザーへ無事に送られれば、statusメッセージがフラッシュデーターとしてセッションに保存されます。送信に失敗すれば、errorメッセージが保存されます。

postRemindコントローラーメソッドの中では、ユーザーへ送信する前に、メッセージインスタンスを更新することができます。

Password::remind(Input::only('email'), function($message)
{
    $message->subject('Password Reminder');
});

ユーザーはコントローラーのgetResetメソッドへルーティングされるリンクを含んだメールを受け取ります。指定されたパスワードリマインダーを識別するために使用されるパスワードリマインダートークンも一緒に送信されてきます。アクションにはpassword.resetビューを返すように、予めコードされていますが、このビューも作成して下さい。トークンはビューに渡され、tokenという名前の隠しフォーム隠しフィールドとして設置されなくてはなりません。このtokenに加え、パスワードリセットフォームにはemailpasswordpassword_confirmationフィールドが必要です。フォームはRemaindersController@postResetメソッドへPOSTで送信して下さい。

シンプルなpassword.resetビューは下のようになるでしょう。

<form action="{{ action('RemindersController@postReset') }}" method="POST">
    <input type="hidden" name="token" value="{{ $token }}">
    <input type="email" name="email">
    <input type="password" name="password">
    <input type="password" name="password_confirmation">
    <input type="submit" value="Reset Password">
</form>

最後に、postResetメソッドがストレージ上のパスワードを実際に変更する責任を負います。このコントローラーアクションの中で、Password::resetメソッドに渡されたクロージャーは、Userpassword属性をセットし、saveメソッドを呼び出しています。もちろん、このクロージャーは、UserモデルがEloquentモデルであると想定しています。しかしながら、アプリケーションのデータベース保管システムに適するように、必要に応じて自由に変更して下さい。

パスワードがうまくリセットし終えたら、ユーザーはアプリケーションのルートへリダイレクトされます。このリダイレクトURLも自由に変更して下さい。パスワードリセットが失敗したら、ユーザーはリセットフォームへ戻るようにリダイレクトされます。そして、errorメッセージがセッションにフラッシュデーターとして保存されます。

パスワードのバリデーション

デフォルトでは、Password::resetメソッドは確認領域と同一であることと、6文字以上であることを確認します。クロージャーを使うPassword::validatorメソッドで、このルールを変更できます。クロージャーの中でどんなパスワードバリデーションも実行できます。パスワードが確認フィールドと一致するかを調べる必要がないことに注意して下さい。これはフレームワークにより、自動的に調べられます。

Password::validator(function($credentials)
{
    return strlen($credentials['password']) >= 6;
});

Note: デフォルトでは、パスワードのリセットトークンは1時間で無効になります。app/config/auth.phpファイルのreminder.expireオプションにより、この時間を変更できます。

暗号化

Laravelはmcrypt PHP拡張による、強力なAES暗号化機能を提供しています。

値を暗号化する

$encrypted = Crypt::encrypt('secret');

注目:app/config/app.phpファイルのkeyオプションに16文字か24文字、32文字のランダムな文字列を確実に設定してください。そうしないと、暗号化された値は安全ではありません。

値を解読する

$decrypted = Crypt::decrypt($encryptedValue);

手法とモードを設定する

暗号化に使用する手法とモードもセットできます。

Crypt::setMode('ctr');

Crypt::setCipher($cipher);

認証ドライバー

Laravelでは最初から、databaseeloquent認証ドライバーが用意されています。他の認証ドライバーを追加するための情報は、認証の拡張に関するドキュメントをご覧ください。

ドキュメント章別ページ

Artisan CLI

ヘッダー項目移動

注目:アイコン:ページ内リンク設置(リンクがないヘッダーへの移動では、リンクがある以前のヘッダーのハッシュをURLへ付加します。

移動

クリックで即時移動します。

設定

適用ボタンクリック後に、全項目まとめて適用されます。

カラーテーマ
和文指定 Pagination
和文指定 Scaffold
Largeスクリーン表示幅
インデント
本文フォント
コードフォント
フォント適用確認

フォントの指定フィールドから、フォーカスが外れると、当ブロックの内容に反映されます。EnglishのDisplayもPreviewしてください。

フォント設定時、表示に不具合が出た場合、当サイトのクッキーを削除してください。

バックスラッシュを含むインライン\Code\Blockの例です。

以下はコードブロックの例です。

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * ユーザに関連する電話レコードを取得
     */
    public function phone()
    {
        return $this->hasOne('App\Phone');
    }
}

設定を保存する前に、表示が乱れないか必ず確認してください。CSSによるフォントファミリー指定の知識がない場合は、フォントを変更しないほうが良いでしょう。

キーボード・ショートカット

オープン操作

PDC

ページ(章)移動の左オフキャンバスオープン

HA

ヘッダー移動モーダルオープン

MS

移動/設定の右オフキャンバスオープン

ヘッダー移動

T

最初のヘッダーへ移動

E

最後のヘッダーへ移動

NJ

次ヘッダー(H2〜H4)へ移動

BK

前ヘッダー(H2〜H4)へ移動

その他

?

このヘルプページ表示
閉じる