LoginSignup
21
13

More than 3 years have passed since last update.

Laravel のルーティングでauthenticate middlewareを使って認証する3つの方法

Last updated at Posted at 2019-09-24

Laravel ルーティングで特定の、もしくは全てのURLに対するアクセスに対して認証をしてから処理を始めたいケースについて紹介します。

具体的には "自分の情報を編集するマイページには、認証したユーザしか入ることはできない" みたいなケースの実装方法です。

方法を三つ紹介します。

  1. routingファイルで個別のパスに対して指定する方法
  2. routingファイルでグループを指定する方法
  3. RouteServiceProviderで特定パス以下全てに指定する方法

環境

  • Laravel 5.8
  • PHP 7.2

前提条件(middleware の有効化)

app/Http/Kernel.php においてmiddlewareに名前をつけられています。おそらくLaravelをインストールするとデフォルトで以下のような記述(もしくはコメントアウトされている)があるのではないかと思います。

    protected $routeMiddleware = [
        'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
        // 以下略
    ]; 

コメントアウトされている場合には、使用できるように //を外してください。

方法1 routingファイルで個別のパスに対して指定する方法

公式ドキュメント(翻訳)の"認証"のセクション書かれているので軽く紹介しておきます。
参考: https://readouble.com/laravel/5.8/ja/authentication.html

Route::get('profile', function() {
    // 認証済みのユーザーのみが入れる
})->middleware('auth');

authミドルウェアをルートに対し指定するときに、そのユーザーに対し認証を実行するガードを指定することもできます。指定されたガードは、auth.php設定ファイルのguards配列のキーを指定します。


public function __construct()
{
    $this->middleware('auth:api');
}

guradの指定に対応するファイルは以下のように書かれると思います。Providersの記述をもとに、DBからSelectしてきてユーザの確認をします。

config/auth.php
    'guards' => [
        'api' => [
            'driver' => 'token',
            'provider' => 'users',
        ],
    ],

    'providers' => [
        'users' => [
            // EloquentModelを指定するケース
            'driver' => 'eloquent',
            'model' => Path\To\EloquentModel\User::class,
        ],
    ],

方法2 routingファイルでグループを指定する方法

さて、上の方法でみた個別のRoutingに追加する方法ですが、いちいち指定するのは面倒だったり、設定し忘れでセキュリティ的な問題が起こってしまったりするので一括で指定したいところです。
同じルーティングファイル内でも、ログイン前のページは制限なし、一方でログイン後のページで認証あり、というような制限をしたい場合にこの方法が便利です。

routingについてのドキュメントを見ると、一括でmiddlewareを指定する方法があるようです。
参考: https://readouble.com/laravel/5.8/ja/routing.html

レート制限の項目に書いてあるのでちょっとわかりづらいのですが、group化したものに対して以下のようにmiddleware設定をすることができます。

Route::middleware('auth:api', 'throttle:60,1')->group(function () {
    // この中に書いたルーティング全てに適用される
    Route::get('/', 'IndexController@index');
});

// ここには適用されない
Route::get('/piyo', 'IndexPiyoController@index');

また、古い方法(Laravel5.2のドキュメントに書いてある)のようですが、以下のような方法で書くこともできます。
参考: https://readouble.com/laravel/5.2/ja/routing.html

Route::group(['middleware' => 'auth:api'], function () {
    Route::get('/', 'IndexController@index');
});

方法3 RouteServiceProvider で指定する方法

ログインが必要なページから投げられるAjax通信なんかは、全てのパスに対して一括で指定したいところです。
その場合には、グループ化する方法より、RouteServiceProviderで指定する方法がより便利です。

routingファイルとして routes/api/service.php があったとして、routingのマッピングをするとともにmiddlewareを設定します。

app/Providers/RouteServiceProvider.php
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;

class RouteServiceProvider extends ServiceProvider
{

    // このメソッドは親のIlluminate\Foundation\Support\Providers\RouteServiceProviderから呼び出されています
    public function map()
    {
        Route::prefix('api')
            // このprefix以下にあるものに全てmiddlewareが適用される
            ->middleware(['auth:api'])
            // Controllerがどこにあるか指定
            ->namespace($this->namespace . '\Api')
            ->group(base_path('routes/api/service.php'));
    }

これを config/app.php で providers 設定をします。

config/app.php

    'providers' => [
        App\Providers\RouteServiceProvider::class,
    ],

参考: https://readouble.com/laravel/5.8/ja/routing.html

終わりに

ここら辺は複雑なので、どのレイヤで認証を入れているのだろう?というのが分かりづらくなりがちだと思います。
しかしそんなに実装パターンがあるわけではないので、この三つを押さえておけばコードリーディングする助けになるのかなと考えてこの記事を書きました。
もっとこういう方法があるよ! とかここが間違っているとかあれば、修正リクエストやコメントいただけると幸いです。

21
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
13