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

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

Avatar for hikohiko hikohiko
August 07, 2019

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

シューマイ0807用

Avatar for hikohiko

hikohiko

August 07, 2019
Tweet

Other Decks in Programming

Transcript

  1. カスタマイズ イズ どこ? 参照テーブル TokenGuardを使用 したトークン認証にて 参照するテーブルを カスタマイズします。 参照カラム 照合するカラム名をカ

    スタマイズします。 認証条件 トークンの一致以外 に、認証に必要な条 件をカスタマイズしま す。 5 デフォルトのToken認証は下記を使用 Guard: TokenGuard Provider: users 「トークンとusersテーブルのapi_tokenカラムを照合する」設定
  2. 7 Model A(テーブル A) Provider A 参照先 イズ どこ? Model

    B(テーブル B) Provider B 【参照先】 Providerとセットで、 config/auth.phpにて管理 例) デフォルトのProviderであるusersは、 App\User(に紐づくテーブル) 参照先を変更する方法は以下 1. Modelの参照テーブルを変更 2. セットになるModelを変更 3. 新たにセットを作成して使用
  3. 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が参照される ], ],
  4. ちなみに 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の参照テーブル = トークンの参照テーブル
  5. 参照カラム イズ どこ 11 # config/auth.php 'guards' => [ 'api'

    => [ 'driver' => 'token', // ここで指定するものを実装する // 'provider' => 'users', 'provider' => 'access_tokens', // 使用するproviderを指定 'hash' => false, ], ], Requestからトークンの取得するのは Guardの役目になります。 トークンの取得方法は Guard毎に定義されるため、 参照するカラムを変更するには TokenGuardの代わりとなる 独自Guardを実装する必要があります。 Request Guard トークンを取得
  6. 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; }
  7. 独自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に参照させたいカラム名を指定
  8. 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)
  9. 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を設定することで、 参照カラムの変更が完了します。
  10. 条件 イズ どこ 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の役目
  11. 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(); }
  12. 独自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に条件追加。
  13. おまけ 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'); }); }
  14. 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)
  15. 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を設定することで、 認証条件の変更が完了します。