Lumen の Auth・Guard・User 認証徹底解説(2)— 自分のアーキテクチャは、自分のものじゃない

Wake
By Wake2019年8月6日約 7 分で読了
Lumen の Auth・Guard・User 認証徹底解説(2)— 自分のアーキテクチャは、自分のものじゃない

Lumen の認証のしくみは、実はそれほど複雑ではありません。でも、ぱっと見ただけでは理解しづらい。それは Lumen が「Laravel のサブシステム」という原罪を背負っていて、ドキュメントからコードまで大きく簡略化されているからです —— Laravel のコードにさかのぼって見ないと、全体像がまるでつかめないほどに(たとえば Lumen の config/auth.php と Laravel の config/auth.php)。

Laravel を経由せず、いきなり Lumen に触れた開発者にとって、問題にぶつかったり機能を足したくなったりしたときに取る行動は、だいたい「公式ドキュメントを探す → ネットの情報を探す → ソースコードを読み解く」のどれかです。ところが公式ドキュメントははっきり書かれておらず、ネットの情報もぼんやり、ソースを追っても(Laravel に比べて)抽象化の層とコード上の情報が足りないせいで、なかなか手強い。全体の構成を整理してまとめるまでに、かなり余分な労力がかかります。

そういうわけで、僕はこのシリーズを書いています。ほかの Lumen だけで来た開発者が、もっと早く全体像をつかんで、遠回りを少しでも減らせればと思っています。

設定ファイルの謎

Lumen の認証まわりの管理を理解するには、設定ファイルから入るのがよい切り口です。ただし、見るのは Laravel の config/auth.php のほうです。このファイルは Lumen 側のものとオプションもパラメータもほぼ同じですが、より充実した情報を与えてくれます。

認証を有効にしたときのデフォルト

'defaults' => [
  'guard' => 'web',
  'passwords' => 'users',
],

設定ファイルの最初のブロックは、システムのデフォルト Guard の名前を web、デフォルトのパスワードリセットモジュールを users と定義しています(パスワードまわりはこのシリーズの対象外です)。

Guard の設定

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

次のブロックは、実際に Guard を登録している部分で、デフォルトでは 2 つあります:

  1. web という名前の Guard。session driver が SessionGuard を動かして実際の処理を行い、ユーザーオブジェクトの提供者は users モジュールです。
  2. api という名前の Guard。token driver が TokenGuard を動かして実際の処理を行い、ユーザーオブジェクトの提供者は users モジュールです。

ユーザーオブジェクトの提供モジュール

'providers' => [
  'users' => [
    'driver' => 'eloquent',
    'model' => App\User::class,
  ],
  // 'users' => [
  //     'driver' => 'database',
  //     'table' => 'users',
  // ],
],

その次のブロックで登録しているのが、ユーザーオブジェクトの提供モジュール です。コメントアウトされたものも含めて 2 種類あります:

  1. users という名前で、eloquent driver が Eloquent を動かすモジュール。
  2. あるいは database driver が Database への直接接続を動かすモジュール。

driver の下にあるほかの設定(modeltable など)は、各 driver 向けのカスタムパラメータなので、いったん無視して大丈夫です。

Lumen に戻る

Laravel 側の設定ファイルを見たところで、Lumen の config/auth.php の中身に戻ってみましょう:

'defaults' => [
  'guard' => env('AUTH_GUARD', 'api'),
],

'guards' => [
  'api' => ['driver' => 'api'],
],

'providers' => [
  //
],

本当にそぎ落とされていると思いませんか?

Laravel と比べて増えているのは、.env ファイルから Guard の割り当てを取ってくる呼び出しくらいです(そしてデフォルトは api という Guard になります)。

一つ気をつけたいのは、Lumen は 'driver' => 'api' と設定していますが、実はシステムの中に ApiGuard なんてものは存在しないことです。api driver が動かしているのは、RequestGuard をベースにした ちょっとしたカスタマイズ版 です。少しややこしいですよね。大丈夫、あとで一つずつ説明していきます。

まとめ

2 つの設定ファイルから、いくつかの登場人物がいることが、ざっくり見えてきます:

  • Named Guard:xxx という名前の Guard。driver と provider の 2 つから成る。
  • Guard Driver:実際の Guard を動かすドライバ。
  • Named Provider:xxx という名前の Provider(User Provider)。driver とほかのパラメータから成る。
  • Provider Driver:実際の User Provider を動かすドライバ。

基本の認証アーキテクチャ

前の設定ファイルの説明と整理から、こんな関係図が描けます。

BaseOnConfig

ある XXX Guard が設定され、有効になると、それは一組の GuardDriver を通じて、ある Guard を動かし、その Guard の中で認証などの処理を行います。さらに XXX Guard 自身も一組の XXX Provider を定義し、指定された ProviderDriver を通じて、ある UserProvider を動かします。

では、この XXX Guard はアーキテクチャの中でどう使われるのでしょう?その前後にいる 2 つの重要な登場人物を、図に足しておきます。

BasicFlow

実際には、Lumen は AuthManager を通じて、使える Guard + User の組み合わせを取得し、認証などの判断を行います。そして、どの Guard/User が使えるかは、config/auth.php の中で定義され、規定されています。ですから、自分で Guard/Driver/Provider を足すときは、設定ファイルに対応する設定を書き加えるのを必ず忘れないでください。そうしないと、システムはそのカスタム部分をきちんと使えません。

おわりに

ここまでで、アーキテクチャの全体像はほぼ見えてきました。その下で実際にオブジェクトがどう動くのか、流れの細部がどう回っているのかは、次の記事で、これらの登場人物とインターフェース型に踏み込んで見ていきます。

カテゴリー:
Wake

Wake

著者について

趣味が高じてフロントエンドとバックエンドの技術を少しかじっているエンジニアです。大好きなプログラミングのほかに、バドミントン、ボードゲーム、読書、料理、ピアノも好きです。今は AI も積極的に使っています。