Laravel には remeber me 機能があるのですが、これは暗号化した Cookie の情報だけで認証を行うので、やや心許ない実装です。
そこで、Laravel フレームワークを拡張して、独自の認証処理ドライバを実装してみました。
ログイントークンテーブル
認証用ログイントークンを保存するテーブルを作成します。
まず、artisan
コマンドでマイグレーションクラスを作成します。
$ php artisan migrate:make make_login_tokens
生成されたマイグレーションクラスにテーブル定義を書いていきます。
<?php use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class MakeLoginTokens extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('login_tokens', function($table) { $table->increments('id'); $table->text('token')->unique(); $table->integer('user_id') ->references('id')->on('users') ->onDelete('cascade')->onUpdate('cascade'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::drop('login_tokens'); } }
マイグレーションを実行して、login_tokensテーブルを生成します。
$ php artisan migrate
認証カスタムドライバの作成
ログイン認証処理は、Auth
クラスが担っています。ただこれは只のファサードでしかなく、実体はIlluminate\Auth\AuthManager
です。Illuminate\Auth\AuthManager
クラスは、認証処理をドライバに委譲しているので、このドライバを差し替えることで、独自の認証処理を行うことができます。
フレームワークにはIlluminate\Auth\Guard
というドライバが用意されているので、これを継承してカスタムドライバを実装します。
今回、実装(オーバーライド)したのはgetUserByRecaller()
メソッドとqueueRecallerCookie()
メソッドです。
getUserByRecaller()
メソッドは、オートログイン時に呼ばれるので、ブラウザから送信された Cookie の値を使って自動ログインを行うようにしています。
queueRecallerCookie ()
メソッドは、ログイン時に呼ばれるので、ログイントークンを生成してDBに登録し、Cookie に埋め込むようにしました。
<?php namespace Acme; use Carbon\Carbon; use Config; use DB; use Illuminate\Auth\Guard; use LoginToken; /** * Class AuthLoginGuard * @package Acme */ class AutoLoginGuard extends Guard { /** * @param mixed $id * @return mixed */ protected function getUserByRecaller($id) { $limit = Carbon::now()->subDays(Config::get('auth.login_token_limit_day')); // gc DB::table(with(new LoginToken)->getTable())->where('updated_at', '<=', $limit)->delete(); $token = LoginToken::where('token', $id)->where('updated_at', '>', $limit)->first(); if (empty($token)) { return null; } $user = parent::getUserByRecaller($token->user_id); if (empty($user)) { return null; } $token->touch(); $this->updateSession($user->id); return $user; } /** * @param string $id */ protected function queueRecallerCookie($id) { $bytes = Config::get('auth.login_token_length') / 2; $token = bin2hex(openssl_random_pseudo_bytes($bytes)); $loginToken = new LoginToken(); $loginToken->token = $token; $loginToken->user_id = $id; $loginToken->save(); parent::queueRecallerCookie($token); } }
カスタムドライバを有効にする
作成したカスタムドライバをフレームワークで有効にします。
Auth::extend()
Auth::extend()
で、Acme\AutologinGuard
クラスをインスタンス化するクロージャを定義します。ドライバ名にはautologin
を指定しています。
Auth::extend('autologin', function($app) { $provider = new EloquentUserProvider($app['hash'], $app['config']['auth.model']); return new AutoLoginGuard($provider, $app['session.store']); });
app/config/auth.php
app/config/auth.php に、このautologin
ドライバを認証ドライバとして利用するように設定します。
'driver' => 'autologin',
さらに、Acme\AutologinGuard
クラスに必要なログイントークンに関する設定も追加します。
'login_token_limit_day' => 30, // ログイントークン有効期間 'login_token_length' => 60, // ログイントークンの長さ
まとめ
独自のカスタムドライバを作成して、Auth
クラスの認証処理を差し替えてみました。
このように Laravel では、フレームワークの処理を置き換えることができるような機構が用意されているので、要件に合わない部分に関しては、好きに変更することができます。
<
p>こうした柔軟性の高さも Laravel の面白いところですね。
- Newer: Laravel コードからフレームワークの起動から終了までの流れを追う
- Older: Laravel IoC コンテナの使い方