ここのところお仕事でLaravelを使った開発をやっております。
Laravelのバージョンは5.5系。
今作っているシステムの設計としては、
まず各モデルごとにAPIを実装して、
データの読み書き削除は全てAPIを経由して処理する、といったもの。
限られたユーザにしか使わせない想定で、
外部アプリとの連携なども想定していないので、
画面からログインの済んでいるユーザのみが、
諸々のデータ操作を出来るようにしたい。
どんな感じで実装に至ったのか、書いていきます。
手っ取り早く解決したい人向け
以下の記事が大変参考になりました。
というか今回やりたかった実装についてそのまま記載されています。
そもそものルーティング設定
APIの処理の実装の際、
ルーティング設定は「routes/api.php」に記載していました。
Route::apiResources([
(中略)
]);
こんな感じで。
ルーティング処理をmiddlewareで囲めば解決……しない!?
「Laravelで認証使いたかったらauthミドルウェアを使いなされ」
という教えのもと、上記ルート定義を次のように書き換えました。
Route::group(['middleware' => ['auth']], function () {
Route::apiResources([
(中略)
]);
});
これにて
「画面でログイン認証が通っていない場合はAPIで処理を実行出来ない」
という実装はクリア。
問題があるとすれば、このままだと
「画面でログイン認証が通っていてもAPIで処理を実行出来ない」
ということですね。
えっ、API叩くときってセッションが空なんですか。
LaravelのAuthまわりのコアな処理にloggerを仕込みまくって確認したところ、
APIでルーティングされている処理を叩いた際、セッションが空だということがわかりました。
ここまで調べた後に、冒頭に紹介したQiitaの記事に行き着いたのですが、
「app/Http/Kernel.php」にて定義しているミドルウェアグループにおいて、
「Web」でのルーティングの場合は「クッキーの暗号化」やら「セッション開始」やらが定義されているのに対し、
「API」でのルーティングの場合はそれらが為されていないのです。
つまりAPI叩く際にもセッションを扱ってくれれば解決、と。
参考にしたQiitaの記事では、元のAPIルーティングのミドルウェアを汚さないように、
新たなルーティング設定を定義するところから実装しています。
が、今回の当方の開発に際しては、セッションとクッキーを使った認証でしかAPIを叩かないため、
デフォルトで記述しているKernelのAPIミドルウェアグループに対し、
直接、定義の変更を加えていきます。
protected $middlewareGroups = [
'web' => [
(中略)
],
'api' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
'throttle:60,1',
'bindings',
],
];
これにて(「routes/api.php」への変更も含めて)、
webでログインしている際はAPIでの処理を実行でき、
ログインしていないときは処理を実行できない、という挙動を実現させることができました。
* * *
今回は、ルーティングごとに呼び出しているミドルウェアに差異が生じていることから、
こうした「一手間」が必要となりました。
外部サービスとの連携を前提とするならば、セッションを使わない認証になるでしょうから、
元々の設定の方が「スッキリ」しています。
むしろ今回のように、画面で認証しているときにしかAPIを叩かせたくない、という実装がレアケースなのかなぁ……
その辺りはもう少し場数を踏んでいけば、わかってくることなのかもしれません。