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

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

hikohiko
August 07, 2019

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

シューマイ0807用

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を設定することで、 認証条件の変更が完了します。