(再翻訳中)Laravel 8.x 認証

イントロダクション

多くのWebアプリケーションは、ユーザーがアプリケーションで認証して「ログイン」する手段を提供しています。この機能をWebアプリケーションに実装することは、複雑でリスクを伴う可能性のある作業になりえます。このためLaravelは、認証を迅速、安全、かつ簡単に実装するために必要なツールを提供するよう努めています。

Laravelの認証機能は、基本的に「ガード」と「プロバイダ」で構成されています。ガードは、リクエストごとにユーザーを認証する方法を定義します。たとえば、Laravelには、セッションストレージとクッキーを使用して状態を維持する「セッション」ガードを用意しています。

プロバイダは、永続ストレージからユーザーを取得する方法を定義します。LaravelはEloquentとデータベースクエリビルダーを使用してユーザーを取得するためのサポートを用意しています。ただし、アプリケーションの必要性に応じて、追加のプロバイダを自由に定義できます。

アプリケーションの認証設定ファイルはconfig/auth.phpにあります。このファイルは、Laravelの認証サービスの動作を微調整できるように、十分なコメントの付いたオプションがいくつか含まれています。

スターターキット

さっそく始めたいですか?新しいLaravelアプリケーションにLaravelアプリケーションスターターキットをインストールしてください。データベースをマイグレーションした後に、ブラウザで/registerやアプリケーションに割り当てた他のURLへアクセスしてください。スターターキットは、認証システム全体のスカフォールドの面倒を見ます。

最終的にLaravelアプリケーションでスターターキットを使用しないことを選択した場合でも、Laravel Breezeスターターキットをインストールすることは、Laravelのすべての認証機能を実際のLaravelプロジェクトに実装する方法を学ぶ素晴らしい機会になるでしょう。Laravel Breezeは認証コントローラー、ルート、ビューを作成するため、これらのファイル内のコードを調べて、Laravelの認証機能を実装する方法を学べます。

データベースの検討

デフォルトでLaravelはapp/Modelsディレクトリに、App\Models\User Eloquentモデルを用意します。このモデルは、デフォルトのEloquent認証ドライバーで使用します。アプリケーションがEloquentを使用していない場合は、Laravelクエリビルダーを使用するdatabase認証プロバイダを使用できます。

App\Models\Userモデルのデータベーススキーマを構築するときは、パスワード列の長さを確実に60文字以上にしてください。もちろん、新しいLaravelアプリケーションに含まれているusersテーブルのマイグレーションでは、あらかじめこの長さを超えるカラムが作成されます。

さらに、users(または同等の)テーブルに、100文字のnullableな文字列remember_tokenカラムを確実に含めてください。このカラムは、アプリケーションへログインするときに「持続ログイン(remember me)」オプションを選択したユーザーのトークンを格納するために使用します。繰り返しますが、新しいLaravelアプリケーションに含まれているデフォルトのusersテーブルのマイグレーションには、すでにこのカラムが含まれています。

エコシステム概要

Laravelは認証に関連する複数のパッケージを提供しています。先へ進む前に、Laravelの一般的な認証エコシステムを確認し、各パッケージの意図と目的について説明します。

まず、認証がどのように機能するかを確認しましょう。Webブラウザーを使用する場合、ユーザーはログインフォームを介してユーザー名とパスワードを入力します。これらのログイン情報が正しい場合、アプリケーションは認証したユーザーに関する情報をユーザーのセッションに保存します。ブラウザに発行されたクッキーにはセッションIDが含まれているため、アプリケーションへの後続のリクエストでユーザーを正しいセッションに関連付けることができます。セッションクッキーを受信すると、アプリケーションはセッションIDに基づいてセッションデータを取得し、認証情報がセッションに保存されていることに注意して、ユーザーを「認証済み」と見なします。

リモートサービスがAPIへアクセスするために認証する必要がある場合はWebブラウザーがないため、通常クッキーは認証に使用されません。代わりにリモートサービスはリクエストごとにAPIトークンをAPIに送信します。アプリケーションは有効なAPIトークンのテーブルに対して受信したトークンを検証し、そのAPIトークンに関連付けられたユーザーによって実行されたものとしてそのリクエストを「認証」します。

Laravelの組み込みブラウザ認証サービス

Laravelは、通常AuthもしくはSessionファサードを介してアクセスされる組み込みの認証およびセッションサービスを持っています。これらの機能は、Webブラウザーから開始された要求に対してクッキーベースの認証を提供します。これらは、ユーザーのログイン情報を確認し、ユーザーを認証できるようにするメソッドを提供しています。さらに、これらのサービスは適切な認証データをユーザーのセッションへ自動的に保存し、ユーザーのセッションクッキーを発行します。これらのサービスの使用方法に関する説明は、このドキュメントに含まれています。

アプリケーションスターターキット

このドキュメントで説明しているように、これらの認証サービスを手動で操作して、アプリケーション独自の認証レイヤーを構築できます。ただし、より素早く開始できるように、認証レイヤー全体の堅牢で最新のスカフォールドを提供する無料パッケージをリリースしました。こうしたパッケージは、Laravel BreezeLaravel JetstreamLaravel Fortifyです。

Laravel Breezeは、ログイン、登録、パスワードのリセット、電子メールの確認、パスワードの確認など、Laravelの全認証機能のシンプルで最小限の実装です。Laravel Breezeのビューレイヤーは、Tailwind CSSによりスタイル設定したシンプルなBladeテンプレートで構成しています。使い始めるには、Laravelのアプリケーションスターターキットのドキュメントを確認してください。

Laravel Fortifyは、Laravelのヘッドレス認証バックエンドであり、クッキーベースの認証や2要素認証、メールアドレス確認や他の機能など、このドキュメントにある多くの機能を実装しています。FortifyはLaravel Jetstreamの認証バックエンドを提供していますし、Laravelで認証する必要があるSPAの認証を提供するために、Laravel Sanctumと組み合わせて独立して使用できます。

Laravel Jetstream和文は、Laravel Fortifyの認証サービスを利用および公開し、美しくモダンなUIにTailwind CSSを使用しているLivewireInertia.jsを使っている、堅牢なアプリケーションのスターターキットです。Laravel Jetstreamにはオプションサポートとして、2要素認証、チームサポート、ブラウザセッション管理、プロファイル管理、およびAPIトークン認証を提供するLaravel Sanctumとの組み込み統合が含まれています。LaravelのAPI認証手法について以降で説明します。

Laravel API認証サービス

Laravelは、APIトークンの管理とリクエストのAPIトークンによる認証を支援する2つのオプションパッケージ、PassportSanctumを提供しています。これらのライブラリとLaravelの組み込みのクッキーベースの認証ライブラリは、相互に排他的ではないことに注意してください。これらのライブラリは主にAPIトークン認証に重点を置いていますが、組み込みの認証サービスはクッキーベースのブラウザ認証に重点を置いています。多くのアプリケーションは、Laravelの組み込みクッキーベースの認証サービスとLaravelのAPI認証パッケージの両方を使用します。

Passport

PassportはOAuth2認証プロバイダであり、さまざまなタイプのトークンを発行できる多くのOAuth2「許可タイプ」を提供します。一般にAPI認証は、堅牢で複雑なパッケージです。しかし、ほとんどのアプリケーションは、OAuth2仕様によって提供される複雑な機能を必要としないため、ユーザーと開発者の両者を混乱させる可能性があります。さらに、開発者は、PassportなどのOAuth2認証プロバイダを使用してSPAアプリケーションまたはモバイルアプリケーションを認証する方法で、長い間混乱してきました。

Sanctum

OAuth2の複雑さと開発者の混乱に対応するため、ウェブブラウザからのファーストパーティのウェブリクエストとトークンによるAPIリクエストの両方を処理できる、よりシンプルで合理化された認証パッケージの構築に着手しました。この目標は、Laravel Sanctumのリリースにより実現しました。これは、APIに加えてファーストパーティのWeb UIを提供するアプリケーションや、バックエンドLaravelアプリケーションとは別に存在するシングルページアプリケーション(SPA)や、モバイルクライアントを提供するアプリケーションに推奨される認証パッケージと考えてください。

Laravel Sanctumは、アプリケーションの認証プロセス全体を管理できるWeb/APIハイブリッド認証パッケージです。これが可能なのは、Sanctumベースのアプリケーションがリクエストを受信すると、Sanctumは最初に認証済みセッションを参照するセッションクッキーがリクエストに含まれているかどうかを判断するからです。Sanctumは、すでに説明したLaravelの組み込み認証サービスを呼び出すことでこれを実現します。リクエストがセッションクッキーを介して認証されていない場合、SanctumはリクエストのAPIトークンを検査します。APIトークンが存在する場合、Sanctumはそのトークンを使用してリクエストを認証します。このプロセスの詳細については、Sanctumの「仕組み」のドキュメントを参照してください。

Laravel Sanctumは、Laravel Jetstream和文)アプリケーションスターターキットに含めることを私たちが選択したAPIパッケージです。なぜなら、これはWebアプリケーションの認証ニーズの大部分に最適であると考えているためです。

要約とスタックの選択

要約すると、アプリケーションがブラウザーを使用してアクセスされる、モノリシックなLaravelアプリケーションを構築している場合は、アプリケーションにLaravelの組み込み認証サービスを使用してください。

次に、アプリケーションがサードパーティによって使用されるAPIを提供している場合は、PassportまたはSanctumのどちらかを選んでください。アプリケーションにAPIトークン認証を提供します。一般に、Sanctumは、API認証、SPA認証、さらに「スコープ(socpe)」や「能力(ability)」のサポートを含むモバイル認証のためのシンプルで完全なソリューションであるため、使える場合はこちらを推奨します。

Laravelをバックエンドで利用するシングルページアプリケーション(SPA)を構築している場合は、Laravel Sanctumを使用するべきでしょう。Sanctumを使用する場合は、[独自のバックエンド認証ルートを手動で実装する](#authenticating-users)か、Laravel Fortifyをユーザー登録、パスワードのリセット、メールの検証などの機能のためのルートとコントローラーを提供するヘッドレス認証バックエンドサービスとして利用する必要があります。

パスポートは、アプリケーションがOAuth2仕様によって提供されるすべての機能を絶対に必要とする場合に選択できます。

また、すぐに始めたい場合はLaravelの人気のある認証スタックと組み込みの認証サービス、LaravelSanctumをあらかじめ使用し、新しいLaravelアプリケーションをすばやく開始する方法として、Laravel Jetstream和文)をおすすめします。。

認証クイックスタート

Note: ドキュメントのこの部分では、Laravelアプリケーションスターターキットを介したユーザーの認証について説明します。これには、すばやく開始するのに便利なUIスカフォールドが含まれています。Laravelの認証システムを直接統合したい場合は、[ユーザーの手動認証](#authenticating-users)に関するドキュメントを確認してください。

スターターキットのインストール

まず、Laravelアプリケーションスターターキットをインストールする必要があります。現在のスターターキットであるLaravel BreezeとLaravel Jetstreamは、認証を新しいLaravelアプリケーションへ組み込むために美しく設計された開始点を提供します。

Laravel Breezeは、ログイン、ユーザー登録、パスワードリセット、メールの確認、パスワードの確認など、Laravelのすべての認証機能の最小限でシンプルな実装です。Laravel Breezeのビューレイヤーは、Tailwind CSSを用いスタイル設定されたシンプルなBladeテンプレートで構成しています。

Laravel Jetstreamは、LivewireInertia.jsとVueを使用する、アプリケーションのスカフォールドのサポートを含む、より堅牢なアプリケーションスターターキットです。さらに、Jetstreamはオプションとして2要素認証、チーム、プロファイル管理、ブラウザーセッション管理、Laravel Sanctumを介するAPIサポート、アカウント削除などのサポートを備えています。

認証済みユーザー取得

認証スターターキットをインストールし、ユーザーがアプリケーションへ登録・認証できるようにした後、多くの場合は現在認証済みのユーザーを操作する必要があります。受信リクエストの処理時、Authファサードのuserメソッドを使用して認証済みユーザーにアクセスできます。

use Illuminate\Support\Facades\Auth;

// 現在認証しているユーザーを取得
$user = Auth::user();

// 現在認証しているユーザーのIDを取得
$id = Auth::id();

別の方法として、ユーザーが一度認証されると、Illuminate\Http\Requestインスタンスを介してその認証済みユーザーへアクセスできます。タイプヒントクラスは、コントローラーメソッドに自動的に依存注入されることを忘れないでください。Illuminate\Http\Requestオブジェクトをタイプヒントすることで、リクエストのuserメソッドを介しアプリケーションのどのコントローラーメソッドからも、認証済みユーザーへ便利にアクセスできます。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class FlightController extends Controller
{
    /**
     * 既存のフライトの情報を更新
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request)
    {
        // $request->user()
    }
}

現在のユーザーが認証済みか判定

受信HTTPリクエストを送ったユーザーが認証されているかを判断するには、Authファサードでcheckメソッドを使用します。ユーザーが認証されている場合、このメソッドはtrueを返します。

use Illuminate\Support\Facades\Auth;

if (Auth::check()) {
    // ユーザーはログイン済み
}

Tip!! checkメソッドを使用してユーザーが認証されているかどうかを判定できますが、通常はミドルウェアを使用して、ユーザーに特定のルート/コントローラーへのアクセスを許す前に、ユーザーが認証されていることを確認します。これについて詳しくは、ルートの保護に関するドキュメントをご覧ください。

ルートの保護

ルートミドルウェアは、認証済みユーザーのみが特定のルートへアクセスできるように、制限するため使用します。LaravelはIlluminate\Auth\Middleware\Authenticateクラスを参照するauthミドルウェアを用意しています。このミドルウェアはあらかじめ、アプリケーションのHTTPカーネルに登録されているため、必要なのはミドルウェアをルート定義に指定することだけです。

Route::get('/flights', function () {
    // 認証済みユーザーのみがこのルートにアクセス可能
})->middleware('auth');

認証されていないユーザーのリダイレクト

authミドルウェアが認証されていないユーザーを検出すると、ユーザーをlogin 名前付きルートにリダイレクトします。この動作は、アプリケーションのapp/Http/Middleware/Authenticate.phpファイルのredirectTo関数を更新することで変更できます。

/**
 * ユーザーをリダイレクトするパスの取得
 *
 * @param  \Illuminate\Http\Request  $request
 * @return string
 */
protected function redirectTo($request)
{
    return route('login');
}

ガードの指定

authミドルウェアをルートへ接続するときに、ユーザーの認証に使用する「ガード」を指定することもできます。指定するガードは、auth.php設定ファイルのguards配列内のキーの1つに対応している必要があります。

Route::get('/flights', function () {
    // 認証済みユーザーのみがこのルートにアクセスできます
})->middleware('auth:admin');

ログイン回数制限

Laravel BreezeまたはLaravel Jetstream スターターキットを使用している場合、ログインの試行へレート制限が自動的に適用されます。デフォルトでは、ユーザーが数回試行した後に正しい資格情報を提供できなかった場合、ユーザーは1分間ログインできません。ログインの回数制限は、ユーザーのユーザー名/メールアドレスとIPアドレスの組み合わせごとに制限します。

Tip!! アプリケーション内の他のルートのレート制限を希望する場合は、レート制限のドキュメントを確認してください。

ユーザーを手動で認証する

Laravelのアプリケーションスターターキットに含まれている認証スカフォールドを必ず使用する必要はありません。このスカフォールドを使用しないことを選択した場合は、Laravel認証クラスを直接使用してユーザー認証を管理する必要があります。心配ありません。簡単です!

Auth ファサードを介してLaravelの認証サービスにアクセスできるように、クラスの最初でAuthファサードを必ずインポートする必要があります。次に、attemptメソッドを見てみましょう。attemptメソッドは通常、アプリケーションの「ログイン」フォームからの認証試行を処理するために使用されます。認証が成功した場合は、ユーザーのセッションを再生成して、セッション固定攻撃を防ぐ必要があります。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class LoginController extends Controller
{
    /**
     * 認証の試行を処理
     *
     * @param  \Illuminate\Http\Request $request
     * @return \Illuminate\Http\Response
     */
    public function authenticate(Request $request)
    {
        $credentials = $request->only('email', 'password');

        if (Auth::attempt($credentials)) {
            $request->session()->regenerate();

            return redirect()->intended('dashboard');
        }

        return back()->withErrors([
            'email' => 'The provided credentials do not match our records.',
        ]);
    }
}

attemptメソッドは、最初の引数にキー/値ペアの配列を受け入れます。配列の値はデータベーステーブルでユーザーを見つけるために使用します。したがって、上例でユーザーは、emailカラムの値により取得されます。ユーザーが見つかった場合、データベースに保存しているハッシュ化したパスワードと、配列でメソッドに渡したpassword値を比較します。フレームワークはデータベース内のハッシュ化したパスワードと比較する前に値を自動的にハッシュするため、受信リクエストのpassword値はハッシュしないでください。2つのハッシュ化したパスワードが一致する場合、認証済みセッションがそのユーザーに対して開始されます。

Laravelの認証サービスは、認証ガードの「プロバイダ」設定に基づいてデータベースからユーザーを取得することを忘れないでください。デフォルトの config/auth.php設定ファイルでは、Eloquentユーザープロバイダが指定されており、ユーザーを取得するときにApp\Models\Userモデルを使用するように指示されています。アプリケーションの必要に基づいて、設定ファイル内のこうした値を変更できます。

認証が成功した場合、attemptメソッドはtrueを返します。それ以外の場合は、falseが返します。

Laravelのリダイレクタが提供するintendedメソッドは、認証ミドルウェアによってインターセプトされる前に、アクセスしようとしたURLへユーザーをリダイレクトします。目的の行き先が使用できない場合のために、このメソッドにはフォールバックURIが指定できます。

追加条件の指定

必要に応じて、ユーザーのメールアドレスとパスワードに加え、認証クエリにクエリ条件を追加することもできます。これのためには、attemptメソッドへ渡す配列にクエリ条件を追加するだけです。たとえば、ユーザーが「アクティブ(active)」としてマークされていることを確認できます。

if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1])) {
    // 認証に成功した
}

Note: これらの例では、emailは必須オプションではなく、単に例として使用しています。データベーステーブルの"username"に対応するカラム名を使用する必要があります。

特定のガードインスタンスへのアクセス

Authファサードのguardメソッドを介して、ユーザーを認証するときに利用するガードインスタンスを指定できます。これにより、完全に分離した認証可能なモデルやユーザーテーブルを使用して、アプリケーションの個別の部分での認証を管理できます。

guardメソッドへ渡たすガード名は、auth.php設定ファイルで設定するガードの1つに対応している必要があります。

if (Auth::guard('admin')->attempt($credentials)) {
    // ...
}

ログアウト

アプリケーションからユーザーをログアウトするには、Authファサードでlogoutメソッドを使用します。これにより、ユーザーセッションの認証情報がクリアされ、アプリケーションへの以降のリクエストが認証されなくなります。

logoutメソッドを呼び出すことに加えて、ユーザーのセッションを無効にして、CSRFトークンを再生成することを推奨します。ユーザーをログアウトした後、通常はユーザーをアプリケーションのルートにリダイレクトします。

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

/**
 * ユーザーをアプリケーションからログアウトさせる
 *
 * @param  \Illuminate\Http\Request $request
 * @return \Illuminate\Http\Response
 */
public function logout(Request $request)
{
    Auth::logout();

    $request->session()->invalidate();

    $request->session()->regenerateToken();

    return redirect('/');
}

持続ログイン

多くのWebアプリケーションでは、ログインフォームに「継続ログイン(remember me)」チェックボックスがあります。アプリケーションで「継続ログイン」機能を提供したい場合は、attemptメソッドの2番目の引数としてブール値を渡すことができます。

この値がtrueの場合、Laravelはユーザーを無期限に、または手動でログアウトするまで認証されたままにします。 usersテーブルには、「継続ログイン(remember me)」トークンを格納するために使用される文字列、remember_tokenカラムを含める必要があります。新しいLaravelアプリケーションに含まれている usersテーブルのマイグレーションには、すでにこのカラムが含まれています。

use Illuminate\Support\Facades\Auth;

if (Auth::attempt(['email' => $email, 'password' => $password], $remember)) {
    // $rememberがtrueならユーザーは持続ログインされる
}

他の認証方法

ユーザーインスタンスの認証

既存のユーザーインスタンスを現在認証されているユーザーとして設定する必要がある場合は、ユーザーインスタンスをAuthファサードのloginメソッドに渡すことができます。指定されたユーザーインスタンスは、Illuminate\Contracts\Auth\Authenticatable契約の実装である必要があります。Laravelに含まれているApp\Models\Userモデルは前もってこのインターフェイスを実装しています。この認証方法は、ユーザーがアプリケーションに登録した直後など、すでに有効なユーザーインスタンスがある場合に役立ちます。

use Illuminate\Support\Facades\Auth;

Auth::login($user);

loginメソッドの2番目の引数へ論理値を渡たせます。この値は、認証されたセッションに「継続ログイン(remember me)」機能が必要かどうかを示します。これはセッションが無期限に、またはユーザーがアプリケーションから自分でログアウトするまで認証され続けることを意味します。

Auth::login($user, $remember = true);

必要に応じて、loginメソッドを呼び出す前に認証ガードを指定できます。

Auth::guard('admin')->login($user);

IDによるユーザー認証

データベースレコードの主キーを使用してユーザーを認証するには、loginUsingIdメソッドを使用できます。このメソッドは、認証するユーザーの主キーを引数に取ります。

Auth::loginUsingId(1);

loginUsingIdメソッドの第2引数として論理値を渡すことができます。この値は、認証されたセッションに「継続ログイン(remember me)」機能が必要かどうかを示します。これはセッションが無期限に、またはユーザーがアプリケーションから自分でログアウトするまで認証され続けることを意味します。

Auth::loginUsingId(1, $remember = true);

ユーザーを1回認証する

onceメソッドを使用して、そのリクエスト1回だけアプリケーションでユーザーを認証できます。このメソッドを呼び出すときは、セッションやクッキーを使用しません。

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

HTTP基本認証

HTTP基本認証は、専用の「ログイン」ページを設定せずに、アプリケーションのユーザーを認証する簡単な方法を提供します。使用するには、auth.basicミドルウェアをルートに指定します。auth.basicミドルウェアはLaravelフレームワークに含まれているため、定義する必要はありません。

Route::get('/profile', function () {
    // 認証されたユーザーのみがこのルートにアクセスできる
})->middleware('auth.basic');

このミドルウェアがルートに接続されると、ブラウザでそのルートへアクセスするときにログイン情報の入力が自動的に求められます。デフォルトでは、auth.basicミドルウェアは、usersデータベーステーブルのemailカラムがユーザーの"username"であると想定します。

FastCGIに関する注記

PHPFastCGIとApacheを使用してLaravelアプリケーションを提供している場合、HTTP基本認証は正しく機能しない可能性があります。これらの問題を修正するために、アプリケーションの.htaccessファイルに次の行を追加できます。

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

ステートレスなHTTP基本認証

セッションでユーザー識別子クッキーを設定せずにHTTP基本認証を使用することもできます。これは主に、HTTP認証を使用してアプリケーションのAPIへの要求を認証することを選択した場合に役立ちます。これを実現するには、onceBasicメソッドを呼び出すミドルウェアを定義します。onceBasicメソッドによってレスポンスが返されない場合、そのリクエストはさらにアプリケーションに渡されます。

<?php

namespace App\Http\Middleware;

use Illuminate\Support\Facades\Auth;

class AuthenticateOnceWithBasicAuth
{
    /**
     * 受信リクエストの処理
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, $next)
    {
        return Auth::onceBasic() ?: $next($request);
    }

}

次に、ルートミドルウェアを登録して、ルートに指定します。

Route::get('/api/user', function () {
    // 認証済みユーザーのみ、このルートにアクセスできる
})->middleware('auth.basic.once');

ログアウト

アプリケーションからユーザーを手動でログアウトするには、Authファサードが提供するlogoutメソッドを使用できます。これにより、ユーザーのセッションから認証情報が削除され、以降のリクエストが認証されなくなります。

logoutメソッドを呼び出すことに加えて、ユーザーのセッションを無効にして、CSRFトークンを再生成することを推奨します。ユーザーをログアウトした後、通常はユーザーをアプリケーションのルートにリダイレクトします。

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

/**
 * ユーザーをアプリケーションからログアウトさせる
 *
 * @param  \Illuminate\Http\Request $request
 * @return \Illuminate\Http\Response
 */
public function logout(Request $request)
{
    Auth::logout();

    $request->session()->invalidate();

    $request->session()->regenerateToken();

    return redirect('/');
}

他のデバイスでのセッションの無効化

Laravelは、現在のデバイスのセッションを無効にすることなく、他のデバイスでアクティブなそのユーザーのセッションを無効にして「ログアウト」するためのメカニズムも提供しています。この機能は通常、ユーザーがパスワードを変更または更新していて、現在のデバイスを認証したまま他のデバイスのセッションを無効にしたい状況で使用します。

開始する前に、Illuminate\Session\Middleware\AuthenticationSessionミドルウェアが存在し、App\Http\Kernelクラスの'webミドルウェアグループがアンコメントされているのを確認する必要があります。

'web' => [
    // ...
    \Illuminate\Session\Middleware\AuthenticateSession::class,
    // ...
],

次に、Authファサードが提供するlogoutOtherDevicesメソッドを使用します。このメソッドは、アプリケーションが入力フォームから受け入れた、ユーザーの現在のパスワードを確認する必要があります。

use Illuminate\Support\Facades\Auth;

Auth::logoutOtherDevices($currentPassword);

logoutOtherDevicesメソッドが呼び出されると、そのユーザーの他のセッションは完全に無効になります。つまり、以前に認証されたすべてのガードから「ログアウト」されます。

パスワードの確認

アプリケーションの構築中、あるアクションを実行させる前、またはユーザーをアプリケーションの機密領域へリダイレクトする前に、ユーザーへパスワードを確認してもらうアクションの発生する場面がしばし起こるでしょう。Laravelはこの行程を簡単にするためのミドルウェアが組み込まれています。この機能を実装するには、2つのルートを定義する必要があります。1つはユーザーにパスワードの確認を求めるビューを表示するルート、もう1つはパスワードの有効性を確認後、ユーザーを目的の行き先にリダイレクトするルートです。

Tip!! 次のドキュメントでは、Laravelのパスワード確認機能を直接統合する方法について説明しています。ただし、もっと早く始めたい場合は、Laravelアプリケーションスターターキットにこの機能のサポートが含まれています!

設定

パスワードを確認したら、ユーザーはその後3時間パスワードを再確認するように求められることはありません。ただし、アプリケーションのconfig/auth.php設定ファイル内のpassword_timeout設定値の値を変更することにより、ユーザーがパスワードの再入力を求められるまでの時間を設定できます。

ルーティング

パスワード確認フォーム

まず、ユーザーにパスワードの確認を要求するビューを表示するルートを定義します。

Route::get('/confirm-password', function () {
    return view('auth.confirm-password');
})->middleware('auth')->name('password.confirm');

ご想像のとおり、このルートによって返されるビューには、passwordフィールドを含むフォームが必要です。さらに、ユーザーがアプリケーションの保護された領域に入ろうとしているため、パスワードを確認する必要があることを説明する、お好みなテキストをビュー内に含めてください。

パスワードの確認

次に、「パスワードの確認」ビューからのフォーム要求を処理するルートを定義します。このルートはパスワードを検証し、ユーザーを目的の行き先にリダイレクトする責任を負っています。

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Redirect;

Route::post('/confirm-password', function (Request $request) {
    if (! Hash::check($request->password, $request->user()->password)) {
        return back()->withErrors([
            'password' => ['The provided password does not match our records.']
        ]);
    }

    $request->session()->passwordConfirmed();

    return redirect()->intended();
})->middleware(['auth', 'throttle:6,1'])->name('password.confirm');

先へ進む前に、このルートをさらに詳しく調べてみましょう。まず、リクエストのpasswordフィールドが、認証済みユーザーのパスワードと実際に一致するか判定されます。パスワードが有効な場合、ユーザーがパスワードを確認したことをLaravelのセッションに通知する必要があります。passwordConfirmedメソッドは、ユーザーのセッションにタイムスタンプを設定します。このタイムスタンプを使用して、ユーザーが最後にパスワードを確認した日時をLaravelは判別できます。最後に、ユーザーを目的の行き先にリダイレクトします。

パスワード確認済みルートの保護

最近パスワード確認を済ませたことが必要なアクションを実行するすべてのルートに、password.confirmミドルウェアが割り当てられていることを確認する必要があります。このミドルウェアはLaravelのデフォルトインストールに含まれており、ユーザーがパスワードを確認した後にその場所へリダイレクトされるように、ユーザーの意図した行き先をセッションに自動的に保存します。ユーザーの意図した行き先をセッションに保存した後、ミドルウェアはユーザーをpassword.confirm名前付きルートにリダイレクトします。

Route::get('/settings', function () {
    // ...
})->middleware(['password.confirm']);

Route::post('/settings', function () {
    // ...
})->middleware(['password.confirm']);

カスタムガードの追加

Authファサードのextendメソッドを使用して独自の認証ガードを定義できます。サービスプロバイダ内のextendメソッドを呼び出す必要があります。LaravelにははじめからAuthServiceProviderが付属しているため、そのプロバイダにコードを配置できます。

<?php

namespace App\Providers;

use App\Services\Auth\JwtGuard;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Auth;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * アプリケーション中の全認証/承認サービスの登録
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

        Auth::extend('jwt', function ($app, $name, array $config) {
            // Illuminate\Contracts\Auth\Guardインスタンスを返す…

            return new JwtGuard(Auth::createUserProvider($config['provider']));
        });
    }
}

上記の例でわかるように、extendメソッドへ渡たすコールバックは、Illuminate\Contracts\Auth\Guardの実装を返す必要があります。このインターフェイスには、カスタムガードを定義するために実装する必要のあるメソッドがいくつか含まれています。カスタムガードを定義したら、auth.php設定ファイルのguards設定でそのガードを参照します。

'guards' => [
    'api' => [
        'driver' => 'jwt',
        'provider' => 'users',
    ],
],

クロージャリクエストガード

カスタムHTTPリクエストベースの認証システムを実装する最も簡単な方法は、Auth::viaRequestメソッドを使用することです。この方法は、単一クロージャーを使用して認証プロセスをすばやく定義できます。

利用するには、AuthServiceProviderbootメソッド内でAuth::viaRequestメソッドを呼び出します。viaRequestメソッドは、最初の引数として認証ドライバー名を受け入れます。この名前には、カスタムガードを説明する任意の文字列を指定できます。メソッドに渡たす2番目の引数は、やってきたHTTPリクエストを受信し、ユーザーインスタンスを返すクロージャである必要があります。認証が失敗した場合は、nullを返します。

use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

/**
 * アプリケーション中の全認証/承認サービスの登録
 *
 * @return void
 */
public function boot()
{
    $this->registerPolicies();

    Auth::viaRequest('custom-token', function (Request $request) {
        return User::where('token', $request->token)->first();
    });
}

カスタム認証ドライバーを定義したら、auth.php設定ファイルのguards設定でドライバーとして指定します。

'guards' => [
    'api' => [
        'driver' => 'custom-token',
    ],
],

カスタムユーザープロバイダの追加

従来のリレーショナルデータベースを使用してユーザーを保存していない場合は、独自の認証ユーザープロバイダでLaravelを拡張する必要があります。Authファサードでproviderメソッドを使用して、カスタムユーザープロバイダを定義します。ユーザープロバイダリゾルバは、Illuminate\Contracts\Auth\UserProviderの実装を返す必要があります。

<?php

namespace App\Providers;

use App\Extensions\MongoUserProvider;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Auth;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * アプリケーション中の全認証/承認サービスの登録
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

        Auth::provider('mongo', function ($app, array $config) {
            // Illuminate\Contracts\Auth\UserProviderのインスタンスを返す…

            return new MongoUserProvider($app->make('mongo.connection'));
        });
    }
}

providerメソッドを使用してプロバイダを登録した後、auth.php設定ファイルで新しいユーザープロバイダに切り替えてください。まず、新しいドライバーを使用するproviderを定義します。

'providers' => [
    'users' => [
        'driver' => 'mongo',
    ],
],

最後に、guards設定でこのプロバイダを参照します。

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],
],

ユーザープロバイダ契約

Illuminate\Contracts\Auth\UserProviderの実装は、MySQLやMongoDBなどの永続ストレージシステムからIlluminate\Contracts\Auth\Authenticatable実装をフェッチする責務を持っています。これら2つのインターフェイスにより、ユーザーデータの保存方法や、認証されたユーザーを表すために使用されるクラスのタイプに関係なく、Laravel認証メカニズムは機能し続けられます。

Illuminate\Contracts\Auth\UserProviderコントラクトを見てみましょう。

<?php

namespace Illuminate\Contracts\Auth;

interface UserProvider
{
    public function retrieveById($identifier);
    public function retrieveByToken($identifier, $token);
    public function updateRememberToken(Authenticatable $user, $token);
    public function retrieveByCredentials(array $credentials);
    public function validateCredentials(Authenticatable $user, array $credentials);
}

retrieveById関数は通常、MySQLデータベースからの自動インクリメントIDなど、ユーザーを表すキーを受け取ります。IDに一致するAuthenticatable実装は、このメソッドにより取得され、返えされる必要があります。

retrieveByToken関数は、一意の$identifierと"remember me" $tokenによってユーザーを取得します。通常、これはremember_tokenのようなデータベースカラムに格納されます。前のメソッドと同様に、トークン値が一致するAuthenticatableの実装をこのメソッドは返す必要があります。

updateRememberTokenメソッドは、$userインスタンスのremember_tokenを新しい$tokenで更新します。「remember me」認証の試行が成功したとき、またはユーザーがログアウトしているときに、新しいトークンをユーザーに割り当てます。

retrieveByCredentialsメソッドは、アプリケーションで認証を試みるときに、Auth::attemptメソッドに渡されたログイン情報の配列を受け取ります。次に、メソッドはこれらのログイン情報に一致するユーザーを永続ストレージへ「クエリ」する必要があります。通常、このメソッドは、`$credentials['username']の値と一致する"username"を持つユーザーレコードを検索する"WHERE"条件でクエリを実行します。このメソッドは、Authenticatableの実装を返す必要があります。この方法では、パスワードの検証や認証を試みるべきではありません。

validateCredentialsメソッドは、指定された$user$credentialsと比較してユーザーを認証する必要があります。たとえば、このメソッドは通常、Hash::checkメソッドを使用して、$user->getAuthPassword()の値を$credentials['password']の値と比較します。このメソッドは、パスワードが有効かどうかを示すtruefalseを返す必要があります。

Authenticatable契約

UserProviderの各メソッドについて説明したので、Authenticatable契約を見てみましょう。ユーザープロバイダは、retrieveByIdretrieveByTokenretrieveByCredentialsメソッドからこのインターフェイスの実装を返す必要があることに注意してください。

<?php

namespace Illuminate\Contracts\Auth;

interface Authenticatable
{
    public function getAuthIdentifierName();
    public function getAuthIdentifier();
    public function getAuthPassword();
    public function getRememberToken();
    public function setRememberToken($value);
    public function getRememberTokenName();
}

このインターフェイスはシンプルです。getAuthIdentifierNameメソッドはユーザーの「主キー」フィールドの名前を返す必要があり、getAuthIdentifierメソッドはユーザーの「主キー」を返す必要があります。MySQLバックエンドを使用する場合、これはユーザーレコードに割り当てられた自動インクリメントの主キーであるでしょう。getAuthPasswordメソッドは、ユーザーのハッシュされたパスワードを返す必要があります。

このインターフェイスにより、使用しているORMまたはストレージ抽象化レイヤーに関係なく、認証システムは任意の「ユーザー」クラスと連携できます。デフォルトでLaravelはapp/Modelsディレクトリに、このインターフェイスを実装するApp\Models\Userクラスを持っています。

イベント

Laravelは、認証プロセス中にさまざまなイベントをディスパッチします。EventServiceProviderでこれらのイベントにリスナを割り振れます。

/**
 * アプリケーションのイベントリスナマッピング。
 *
 * @var array
 */
protected $listen = [
    'Illuminate\Auth\Events\Registered' => [
        'App\Listeners\LogRegisteredUser',
    ],

    'Illuminate\Auth\Events\Attempting' => [
        'App\Listeners\LogAuthenticationAttempt',
    ],

    'Illuminate\Auth\Events\Authenticated' => [
        'App\Listeners\LogAuthenticated',
    ],

    'Illuminate\Auth\Events\Login' => [
        'App\Listeners\LogSuccessfulLogin',
    ],

    'Illuminate\Auth\Events\Failed' => [
        'App\Listeners\LogFailedLogin',
    ],

    'Illuminate\Auth\Events\Validated' => [
        'App\Listeners\LogValidated',
    ],

    'Illuminate\Auth\Events\Verified' => [
        'App\Listeners\LogVerified',
    ],

    'Illuminate\Auth\Events\Logout' => [
        'App\Listeners\LogSuccessfulLogout',
    ],

    'Illuminate\Auth\Events\CurrentDeviceLogout' => [
        'App\Listeners\LogCurrentDeviceLogout',
    ],

    'Illuminate\Auth\Events\OtherDeviceLogout' => [
        'App\Listeners\LogOtherDeviceLogout',
    ],

    'Illuminate\Auth\Events\Lockout' => [
        'App\Listeners\LogLockout',
    ],

    'Illuminate\Auth\Events\PasswordReset' => [
        'App\Listeners\LogPasswordReset',
    ],
];

ドキュメント章別ページ

ヘッダー項目移動

注目:アイコン:ページ内リンク設置(リンクがないヘッダーへの移動では、リンクがある以前のヘッダーのハッシュを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)へ移動

その他

?

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