ユーザー認証(10)Laravel 5.2 マルチ認証では、会員と管理者に対して異なるDBテーブルをもとに認証を設定しました。
また、
前回では、違うHasherの使用を試みました。
今回は、マルチ認証のときに異なるHasherを用いるケースについて考えてみましょう。そうたくさん起こるケースでないかもしれませんが、私のクライアントのシステムでは実際に起こるケースです。1つのシステムにおいて、「会員」と「管理者」と「店舗管理者」が存在し、それぞれの認証は異なるHasherを使用しています。特に「管理者」は複数のシステムで共有するもので、その認証のためのサーバーが違うマシンに存在します。
まず直面する問題は、Laravelの5.2のマルチ認証では、このような状況にはシンプルに対応できないことです。
config/auth.php
のproviders
では、それぞれのprovider
においてhasherの設定がないのです。
.. 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\User::class, ], 'admin_users' => [ 'driver' => 'eloquent', 'model' => App\AdminUser::class, ], ], ..
また、前回のように、グローバルでHasherを変えることもできません。
「会員」の認証のときには、デフォルトのHasherを使用し、「管理者」の認証のときには、違うHasherを使用できるのが理想です。
まず、Auth
のサービスがどう初期化されているか追跡してみましょう。
AuthServiceProvider
で、ユーザー認証のサービスauth
が登録されます。そこでは、AuthManager
のクラスが使用されます。
protected function registerAuthenticator() { $this->app->singleton('auth', function ($app) { $app['auth.loaded'] = true; return new AuthManager($app); }); $this->app->singleton('auth.driver', function ($app) { return $app['auth']->guard(); }); }
AuthManager
では、config/auth.php
の設定を読み込み、provider
を作成します。その作成は、CreatesUserProviders
で行われます。
.. public function createSessionDriver($name, $config) { $provider = $this->createUserProvider($config['provider']); ..
provider
のdriver
は、先のconfig/auth.php
ではeloquent
と設定されているので、以下のメソッドでオブジェクトが作成されます。
.. protected function createEloquentProvider($config) { return new EloquentUserProvider($this->app['hash'], $config['model']); } ..
やっとたどり着きましたね。そうprovider
の作成時に、グローバルのHasher app['hash']
がパラメとして渡されているのです。
ここを変えることができれば、認証のHasherを変えることできるのです。変更するには、新規の認証のためのdriver
を使用することも可能です。しかし、以下のEloquentUserProvider
を見ると、オブジェクトが作成された後でもHasherを変えることが可能のようです。
... /** * Sets the hasher implementation. * * @param \Illuminate\Contracts\Hashing\Hasher $hasher * @return $this */ public function setHasher(HasherContract $hasher) { $this->hasher = $hasher; return $this; } ...
ここまで理解すると、あとはそう難しくはありません。
まずは、config/auth.php
において、どのHasherのサービスを使用するか指定しましょう。
... 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\User::class, 'hasher' => Illuminate\Hashing\BcryptHasher::class ], 'admin_users' => [ 'driver' => 'eloquent', 'model' => App\AdminUser::class, 'hasher' => App\Services\MD5Hasher::class ], ], ...
上のhasher
はまったくLaravelのコードでは使用されませんが、今回の目的でHasherを指定するにはベストの場所と思いませんか!
次に、管理者のAuthControllerにおいて、
... class AuthController extends Controller { use AuthenticatesAndRegistersUsers, ThrottlesLogins { getCredentials as getCredentialsTrait; } protected $redirectTo = '/admin/home'; protected $guard = 'admin'; protected $redirectAfterLogout = 'admin/login'; //ログイン後のリダイレクト先 protected $username = 'email'; // DBテーブルのログインに使用される項目 protected $registerView = 'admin.auth.register'; // 登録に使用されるテンプレート protected $loginView = 'admin.auth.login'; // ログインに使用されるテンプレート protected $hasher; public function __construct() { $hasher_class = config('auth.providers.admin_users.hasher'); $this->hasher = new $hasher_class; \Auth::guard($this->guard)->getProvider()->setHasher($this->hasher); $this->middleware('guest:admin', ['except' => 'logout']); } ...
会員と違うテンプレートを用意するために、テンプレートの場所を指定していることにも注意してください。すべて変数の指定で可能です。
PasswordControllerにおいても同様な設定をします。
class PasswordController extends Controller { use ResetsPasswords; protected $redirectTo = '/admin/home'; // ログイン後のリダイレクト先 protected $guard = 'admin'; protected $linkRequestView = 'admin.auth.passwords.email'; // パスワードのリセットリンクを送信してもらう画面のテンプレート protected $resetView = 'admin.auth.passwords.reset'; // パスワードリセット画面のテンプレート protected $subject = '管理者のパスワードリセット'; // 送信メールの件名 public function __construct() { $hasher_class = config('auth.providers.admin_users.hasher'); \Auth::guard($this->guard)->getProvider()->setHasher(new $hasher_class); $this->middleware('guest:admin'); } }
最後に、管理者へのパスワードリセットのメールのテンプレートは、以下のように、config/auth.php
で可能です。
... 'passwords' => [ 'users' => [ 'provider' => 'users', 'email' => 'user.auth.emails.password', 'table' => 'password_resets', 'expire' => 60, ], 'admin_users' => [ 'provider' => 'admin_users', 'email' => 'admin.auth.emails.password', 'table' => 'admin_password_resets', 'expire' => 60, ], ], ];メルマガ購読の申し込みはこちらから。