Laravel: 認証のカスタマイズ
標準のデータベース以外のソースで認証をおこなうため、カスタマイズする。
参考) https://laravel.com/docs/6.x/authentication#adding-custom-guards
環境
- Laravel 6
概要
以下のインタフェースを実装したクラスを作成する。
Interface | Purpose | |
---|---|---|
Guard | Illuminate\Contracts\Auth\Guard | 認証要求を処理し、認証結果を保持管理する。 |
Provider | Illuminate\Contracts\Auth\UserProvider | 認証情報から User のインスタンスを返す。 |
User | Illuminate\Contracts\Auth\Authenticatable | 認証情報を持っているクラス。 |
どの実装を使用するかは、config/auth.php に設定する。
// config/auth.php
return [
...
'guards' => [
'web' => [
'driver' => 'session', ★使用する Guard の名前
'provider' => 'users', ★↓に定義した providers の名前
],
'api' => [
'driver' => 'token',
'provider' => 'users',
'hash' => false,
],
],
'providers' => [
'users' => [
'driver' => 'eloquent', ★使用する Provider の名前
'model' => App\User::class, ★と、パラメタ
],
],
...
];
標準で用意されている Guard
driver の名前 | 実装 | 備考 |
---|---|---|
request | Illuminate\Auth\RequestGuard | |
session | Illuminate\Auth\SessionGuard | 認証結果をセッションに保持する。 |
token | Illuminate\Auth\TokenGuard |
標準で用意されている Provider
driver の名前 | 実装 | 備考 |
---|---|---|
database | Illuminate\Auth\DatabaseUserProvider | DB による認証。 |
eloquent | Illuminate\Auth\EloquentUserProvider | Eloquent 経由 DB による認証。User の Eloquent モデルには Illuminate/Auth/Authenticatable トレイトを use するだけで実装完了。 |
ログインシーケンス
ログインユーザーの取得
実装
参考) Adding Custom User Providers - Laravel
ユーザープロバイダクラスを作成
UserProvider
インタフェースを実装した、ユーザーを提供するプロバイダクラスを作成する。実装する関数は以下の通り。
Method | Description |
---|---|
retrieveById | ID からユーザーインスタンスを生成する。 |
retrieveByToken | ID と Remember Token からユーザーインスタンスを取得する。ログイン時に「Remember me」をチェックし、ログインセッション切れ後に自動再ログインするときに使用する。「Remember me」機能を実装しない場合は使用されない。 |
updateRememberToken | 「Remeber me」をチェックしてログインした際に呼ばれるので、Remember Token を保存する。「Remember me」機能を実装しない場合は使用されない。 |
retrieveByCredentials | ログイン時に入力された認証情報(ユーザー名、パスワード等)からユーザーインスタンスを生成する。パスワードを含む認証情報が渡ってくるが、ここで認証はしないこと。 |
validateCredentials | 取得したユーザーインスタンスと入力された認証情報をもとに、ここで認証をおこなう。 |
実際のデータソースへのアクセスをおこなう MyUserRepository
クラスが存在する場合の例。(「Remeber me」機能の実装は省略した。)
<?php
namespace App\Providers;
use App\Model\MyUserRepositoryInterface;
class MyUserProvider implements UserProvider
{
protected $userReposotiry;
public function __construct(MyUserRepositoryInterface $userReposotiry)
{
$this->userReposotiry = $userReposotiry;
}
public function retrieveById($identifier): ?Authenticatable
{
return $this->userReposotiry->getUserById($identifier);
}
public function retrieveByToken($identifier, $token): ?Authenticatable
{
throw new Exception(sprintf('Not implemented: %s->%s()', self::class, __FUNCTION__));
}
public function updateRememberToken(Authenticatable $user, $token): void
{
throw new Exception(sprintf('Not implemented: %s->%s()', self::class, __FUNCTION__));
}
public function retrieveByCredentials(array $credentials): ?Authenticatable
{
if (!isset($credentials['email'])) {
return null;
}
return $this->userReposotiry->getUserByLogin($credentials['email']);
}
public function validateCredentials(Authenticatable $user, array $credentials): bool
{
if (!isset($credentials['email']) || !isset($credentials['password'])) {
return false;
}
return $this->userReposotiry->authenticateUser($credentials['email'], $credentials['password']);
}
}
作成したユーザープロバイダクラスを登録
<?php
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Auth;
class AuthServiceProvider extends ServiceProvider
{
public function boot()
{
...
Auth::provider('my_user', function ($app, array $config) {
return $app->make(MyUserProvider::class);
});
}
}
作成したユーザープロバイダクラスを設定
config/auth.php の provider
に追加し、guards
から指定する。
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'my_users',
],
],
'providers' => [
'my_users' => [
'driver' => 'my_user',
],
],
ユーザークラスを作成
プロバイダが返すユーザーインスタンスは、Authenticatable
インタフェースを実装する必要がある。
Method | Description |
---|---|
getAuthIdentifierName | ユーザーのプライマリキー名を返す。(例: "id" ) |
getAuthIdentifier | ユーザーのプライマリキーを返す。 |
getAuthPassword | ユーザーのハッシュ化されたパスワードを返す。「Remember me」機能を実装しない場合は使用されない。 |
getRememberToken | ユーザーの Remember Token を返す。「Remember me」機能を実装しない場合は使用されない。 |
setRememberToken | ユーザーの Remember Token を設定する。「Remember me」機能を実装しない場合は使用されない。 |
getRememberTokenName | ユーザーの Remember Token 名を返す。「Remember me」機能を実装しない場合は使用されない。 |
namespace App\Model;
use Exception;
use Illuminate\Contracts\Auth\Authenticatable;
/**
* MyUser model
*/
class MyUser implements Authenticatable
{
public function getAuthIdentifierName()
{
return 'id';
}
public function getAuthIdentifier()
{
return $this->getId();
}
public function getAuthPassword(): string
{
throw new Exception(sprintf('Not implemented: %s->%s()', self::class, __FUNCTION__));
}
public function getRememberToken(): string
{
throw new Exception(sprintf('Not implemented: %s->%s()', self::class, __FUNCTION__));
}
public function setRememberToken($value): void
{
throw new Exception(sprintf('Not implemented: %s->%s()', self::class, __FUNCTION__));
}
public function getRememberTokenName(): string
{
throw new Exception(sprintf('Not implemented: %s->%s()', self::class, __FUNCTION__));
}
}