Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Laravelで認証カスタマイズ_シューマイ0807

Cf435ea030fdd03a56c6ce86ae83ef9e?s=47 hikohiko
August 07, 2019

 Laravelで認証カスタマイズ_シューマイ0807

シューマイ0807用

Cf435ea030fdd03a56c6ce86ae83ef9e?s=128

hikohiko

August 07, 2019
Tweet

Other Decks in Programming

Transcript

  1. 【今夜勝ちたい】 LaravelでAPI認証カスタマイズ 【シューマイ】Tech Lead Engineerから最新技術を学べ! Laravel編 2019.08.07 株式会社プラムザ 志村和彦

  2. 自己紹介 志村 和彦(Shimura Kazuhiko) 所属:株式会社プラムザ    PrimeOrder事業部 AWSとかちょっとできる。 VBもちょっとできる。 スマスピで遊ぼうと企んでいる。 2

  3. “ 今回は 「デフォルトで用意されているAPI のToken認証をカスタマイズして みよう」 という話です。 3

  4. 4 model (テーブル) Provider Request Guard ① 認証情報を取得 大体の認証の流れ アプリ本体

    ② 照合 ③ 被認証者情報 &Requestがアプリへ
  5. カスタマイズ イズ どこ? 参照テーブル TokenGuardを使用 したトークン認証にて 参照するテーブルを カスタマイズします。 参照カラム 照合するカラム名をカ

    スタマイズします。 認証条件 トークンの一致以外 に、認証に必要な条 件をカスタマイズしま す。 5 デフォルトのToken認証は下記を使用 Guard: TokenGuard Provider: users 「トークンとusersテーブルのapi_tokenカラムを照合する」設定
  6. 参照テーブル え?user?もうトークン格納用のテーブル定義し ちゃったよ? 1

  7. 7 Model A(テーブル A) Provider A 参照先 イズ どこ? Model

    B(テーブル B) Provider B 【参照先】 Providerとセットで、 config/auth.phpにて管理 例) デフォルトのProviderであるusersは、 App\User(に紐づくテーブル) 参照先を変更する方法は以下 1. Modelの参照テーブルを変更 2. セットになるModelを変更 3. 新たにセットを作成して使用
  8. config/auth.phpを修正 8 'guards' => [ 'api' => [ 'driver' =>

    'token', // TokenGuardが使用される // 'provider' => 'users', 'provider' => 'access_tokens', // 使用するproviderを指定 'hash' => false, ], ], 'providers' => [ // デフォルトで設定されているProvider 'users' => [ 'driver' => 'eloquent', ‘model' => App\User::class, ], // providerに指定した名前で追加 'access_tokens' => [ 'driver' => 'eloquent', 'model' => App\AccessToken::class, // 指定したModelに対応したtableが参照される ], ],
  9. ちなみに 9 # App/AccessToken.php <?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use

    Illuminate\Database\Eloquent\SoftDeletes; class AccessToken extends Model { protected $table = 't_access_tokens'; // テーブル名を指定 use SoftDeletes; // modelの参照テーブル = トークンの参照テーブル
  10. 参照カラム api_token・・・ access_tokenって名前にしちゃったよ 2

  11. 参照カラム イズ どこ 11 # config/auth.php 'guards' => [ 'api'

    => [ 'driver' => 'token', // ここで指定するものを実装する // 'provider' => 'users', 'provider' => 'access_tokens', // 使用するproviderを指定 'hash' => false, ], ], Requestからトークンの取得するのは Guardの役目になります。 トークンの取得方法は Guard毎に定義されるため、 参照するカラムを変更するには TokenGuardの代わりとなる 独自Guardを実装する必要があります。 Request Guard トークンを取得
  12. TokenGuard イズ なに? 12 # vendor/laravel/framework/src/Illuminate/Auth/TokenGuard.php public function __construct( UserProvider

    $provider, Request $request, $inputKey = 'api_token', // 取得キー名 ここ変えたい! $storageKey = 'api_token', // 参照キー名 ここ変えたい! $hash = false) { $this->hash = $hash; $this->request = $request; $this->provider = $provider; $this->inputKey = $inputKey; $this->storageKey = $storageKey; } ・トークン取得元、参照キー名などを定義し、リクエストからトークンを取得 ・providerを介して指定モデル(テーブル)、条件でトークン該当データを照合 public function getTokenForRequest() { $token = $this->request->query($this->inputKey); if (empty($token)) { $token = $this->request->input($this->inputKey); } if (empty($token)) { $token = $this->request->bearerToken(); } if (empty($token)) { $token = $this->request->getPassword(); } return $token; }
  13. “ 訪問者(リクエスト)から鍵を受け 取って門の中のproviderに照 合を頼む。 まさにGuard(守衛) 13

  14. 独自Guard フロム TokenGuard 14 # app/Services/Auth/AccessTokenGuard.php use Illuminate\Auth\TokenGuard; use Illuminate\Contracts\Auth\UserProvider;

    use Illuminate\Http\Request; class AccessTokenGuard extends TokenGuard { public function __construct(UserProvider $provider, Request $request) { // 親(TokenGuard)のconstructのinputkey&storageKeyに参照させたいkey名を指定 parent::__construct($provider, $request, 'access_token', 'access_token'); } } TokenGuardを修正するわけにもいかないので extendして実装。 inputkey& storagekeyに参照させたいカラム名を指定
  15. auth.phpで使えるようにする 15 # app/Providers/AuthServiceProvider.php <?php namespace App\Providers; use App\Services\Auth\AccessTokenGuard; //

    実装したGuardを追加 use Illuminate\Support\Facades\Auth; // Guardの追加メソッド(extend)を使用するためにusr use Illuminate\Support\Facades\Gate; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; class AuthServiceProvider extends ServiceProvider { public function boot() { $this->registerPolicies(); Auth::extend('access_token', function ($app, $name, array $config) { return new AccessTokenGuard(Auth::createUserProvider($config['provider']), $app['request']); }); } } AuthServiceProvider内で”access_token”という名前でGuardを追加(Auth::extend)
  16. auth.phpで設定 16 # onfig/auth.php 'guards' => [ 'api' => [

    'driver' => 'access_token', // 追加したaccess_tokenという名前のguardを指定 // 'provider' => 'users', 'provider' => 'access_tokens', // 使用するproviderを指定 'hash' => false, ], ], guards内のdriverに追加したGuardを設定することで、 参照カラムの変更が完了します。
  17. 認証条件 何・・・だと? 有効期限なんて、そんなのありかよ。 3

  18. 条件 イズ どこ 18 # config/auth.php 'providers' => [ 'users'

    => [ 'driver' => 'eloquent', 'model' => App\Models\User::class, ], 'access_tokens' => [ 'driver' => 'eloquent', // ここに指定するものを実装 'model' => App\Models\AccessToken::class, ], ], Guard側で指定するキー名は別として、 参照先での照合条件は Providerで定義されため、 認証条件を追加するには独自 Providerを実装する必要があります。 もともと指定されている eloquent(Illuminate\Auth\EloquentUserProvider)を拡張していきます。 model (テーブル) Provider トークンの照合はProviderの役目
  19. EloquentUserProvider イズ なに? 19 # Illuminate\Auth\EloquentUserProvider public function retrieveByCredentials(array $credentials)

    { if (empty($credentials) || (count($credentials) === 1 && array_key_exists('password', $credentials))) { return; } $query = $this->newModelQuery(); ・Guardから渡された情報を元に認証関連操作(照合、取得、アップデート) ・照合結果をGaurdに渡す     foreach ($credentials as $key => $value) { if (Str::contains($key, 'password')) { continue; } if (is_array($value) || $value instanceof Arrayable) { $query->whereIn($key, $value); } else { $query->where($key, $value); } } return $query->first(); }
  20. “ 守衛(Guard)から鍵を受け取っ て照合・データ提供を行う。 まさにProvider(提供者) 20

  21. 独自Provider フロム Eloquent 21 # app/Providers/AccessTokenProvider.php <?php namespace App\Providers; use

    App\Models\AccessToken; use Illuminate\Auth\EloquentUserProvider; use Illuminate\Support\Str; class AccessTokenProvider extends EloquentUserProvider { public function retrieveByCredentials(array $credentials) {     (中略) // 生成されたqueryに有効期限関連の条件追加(pp/AccessToken.phpで定義) $query = AccessToken::validateExpire($query);  // 結果返却 return $query->first(); } } TokenGuardと同様にextendして実装。retrieveByCredentialsに条件追加。
  22. おまけ 22 AccessToken::validateExpire # app/AccessToken.php <?php namespace App\Models; use Illuminate\Database\Eloquent\Model;

    use Illuminate\Database\Eloquent\SoftDeletes; class AccessToken extends Model {   (中略) public static function validateExpire($query) { // 渡されたクエリに条件を追加して返す return $query ->where('is_expired', false) ->where(function ($q) { $q->orWhere('expired_at', '>=', date("Y-m-d H:i:s")); $q->orWhereNull('expired_at'); }); }
  23. auth.phpで使えるようにする 23 # app/Providers/AuthServiceProvider.php <?php namespace App\Providers; use App\Providers\AccessTokenProvider; //実装したproviderを追加

    use App\Services\Auth\AccessTokenGuard; (中略) class AuthServiceProvider extends ServiceProvider { public function boot() { $this->registerPolicies(); Auth::extend('access_token', function ($app, $name, array $config) { return new AccessTokenGuard(Auth::createUserProvider($config['provider']), $app['request']); });     Auth::provider('access_token', function ($app, array $config) { return new AccessTokenProvider($app['hash'], $config['model']); }); } } AuthServiceProvider内で”access_token”という名前でProviderを追加(Auth::provider)
  24. auth.phpで設定 24 # onfig/auth.php 'providers' => [ 'users' => [

    'driver' => 'eloquent', 'model' => App\Models\User::class, ], 'access_tokens' => [ // 'driver' => 'eloquent', 'driver' => 'access_token', // 追加したaccess_tokenという名前のproviderを指定 'model' => App\Models\AccessToken::class, ], ], providers内のdriverに追加したProviderを設定することで、 認証条件の変更が完了します。
  25. ざっくりまとめると 参照テーブル auth.phpのproviderの参照するモデルを書き換える 参照カラム Auth.phpのguards - driverに設定するguardを実装(TokenGuard extend) AuthServiceProvider.phpにて登録。auth.phpに設定。 認証条件

    Auth.phpのprobiders - driverに設定するproviderを実装 (EloquentUserProvider extend) AuthServiceProvider.phpにて登録。auth.phpに設定。 25
  26. “ カスタマイズをすることで ”各々が何をしているか” “どんなメソッドがあるのか” “なぜそんな動きをするのか” といった理解も深まります。 26

  27. “ How (どうやるのか) & Why (なぜそうなるのか) 27

  28. 28 Thanks? 終わりのその前に

  29. 29 告知

  30. 30 Prime Order next stage

  31. 31 お客様の業務課題・業務フローを改善し、 お客様のビジネスに、 私たちのいる社会に、 新しい価値を生み出すことを目的とする。 それが Prime Order事業部です。 私たちはフリーランスエンジニアの方を募集しています。 Prime

    Order 参画者募集
  32. 32 ご興味をもっていただけた方 会社訪問のお申込みはこちらから https://goo.gl/forms/ICdr6QwE2mAjy7oM2

  33. 33 ご静聴ありがとうございました。 今度こそ本当に終わりです