raid / guardian
Raid 认证包
Requires
- php: ^8.2
- laravel/sanctum: ^4.0
README
此包是 Laravel Sanctum 包的包装器。[Laravel Sanctum] 它引入了新的概念到认证流程中,例如
要求
php >= 8.2
laravel/sanctum >= 4.0
安装
composer require raid/guardian
配置
通过运行以下命令将配置文件发布到您的项目
php artisan vendor:publish --provider="Raid\Guardian\Providers\GuardianServiceProvider"
用法
让我们看看使用此包进行认证的基本用法。
class LoginController extends Controller { public function __invoke(Request $request, UserGuardian $guardian) { $authenticator = $guardian->attempt($request->only([ 'email', 'password', ])); return response()->json([ 'authenticator' => $authenticator->getName(), 'token' => $authenticator->getStringToken(), 'resource' => $authenticator->getAuthenticatable(), 'errors' => $authenticator->errors()->toArray(), ]); } }
Guardian
将处理认证过程,并返回一个包含认证信息的 Authenticator
实例。
Guardian
类定义了将被用于查找用户的 Authenticatable
类,它还定义了用于认证用户的 Authenticators
。
Authenticator
类依赖于 Matchers
来查找已认证的用户,然后它可以运行一些 Norms
和 Sequences
来完成认证过程。
让我们深入了解 Authenticatable
、Guardian
和 Authenticator
类。
可认证的
Authenticates
类将用于查找用户,并在找到时返回 Illuminate\Contracts\Auth\Authenticatable
实例。
<?php namespace App\Models; use Illuminate\Contracts\Auth\Authenticatable; use Laravel\Sanctum\HasApiTokens; use Illuminate\Foundation\Auth\User as IlluminateUser; use Raid\Guardian\Authenticatable\Contracts\AuthenticatableInterface; class User extends IlluminateUser implements AuthenticatableInterface { use HasApiTokens; public function findForAuthentication(string $attribute, mixed $value): ?AuthenticatableInterface { return $this->where($attribute, $value)->first(); } }
Authenticatable
类必须实现 AuthenticatableInterface
接口。
Authenticatable
类必须定义 findForAuthentication
方法。
findForAuthentication
方法接受两个参数:$attribute
和 $value
,这两个参数从提供的凭证中传递。
findForAuthentication
方法必须返回找到的 Illuminate\Contracts\Auth\Authenticatable
实例。
Guardian
Guardian
类将用于定义 Authenticatable
类和 Authenticators
,以便通过不同的流程处理认证。
您可以使用以下命令创建一个新的 guardian 类
php artisan raid:make-guardian UserGuardian
这将输出以下代码
<?php namespace App\Http\Authentication\Guardians; use Raid\Guardian\Guardians\Guardian; use Raid\Guardian\Guardians\Contracts\GuardianInterface; class UserGuardian extends Guardian implements GuardianInterface { public const NAME = ''; protected string $authenticatable; protected array $authenticators = []; }
让我们配置 Guardian
类。
<?php namespace App\Http\Authentication\Guardians; use App\Models\User; use App\Http\Authentication\Guardians\SystemAuthenticator; use Raid\Guardian\Guardians\Guardian; use Raid\Guardian\Guardians\Contracts\GuardianInterface; class UserGuardian extends Guardian implements GuardianInterface { public const NAME = 'user'; protected string $authenticatable = User::class; protected array $authenticators = [ SystemAuthenticator::class, ]; }
Guardian
类必须实现 GuardianInterface
。
Guardian
类必须扩展 Guardian
类。
Guardian
类应该定义 name
常量。
Guardian
类必须定义 authenticatable
属性。
Guardian
类应该定义 authenticators
属性。
Guardian
类可以处理其定义的任何 authenticators
的认证。
您可以使用两种方式定义 authenticators
authenticators
属性config\authentication.php
文件
<?php use App\Http\Authentication\Guardians\UserGuardian; use App\Http\Authentication\Authenticators\SystemAuthenticator; return [ 'guardian_authenticators' => [ UserGuardian::class => [ SystemAuthenticator::class, ], ], ];
此定义允许您使用认证器名称通过不同的 Authenticators
认证用户。
如果您没有传递任何认证器,则将使用默认认证器。
<?php class LoginController extends Controller { public function __invoke(Request $request, UserGuardian $guardian) { $credentials = $request->only([ 'email', 'password', ]); $authenticator = $guardian->attempt($credentials, 'system'); } }
认证器
Authenticator
类将用于使用传递的 Authenticatable
类和 Credentials
处理认证过程。
您可以使用以下命令创建一个新的认证器类
php artisan raid:make-authenticator SystemAuthenticator
这将输出以下代码
<?php namespace App\Http\Authentication\Authenticators; use Raid\Guardian\Authenticators\Authenticator; use Raid\Guardian\Authenticators\Contracts\AuthenticatorInterface; class SystemAuthenticator extends Authenticator implements AuthenticatorInterface { public const NAME = ''; }
让我们配置 Authenticator
类。
<?php namespace App\Http\Authentication\Authenticators; use Raid\Guardian\Authenticators\Authenticator; use Raid\Guardian\Authenticators\Contracts\AuthenticatorInterface; class SystemAuthenticator extends Authenticator implements AuthenticatorInterface { public const NAME = 'system'; }
Authenticator
类必须实现 AuthenticatorInterface
。
Authenticator
类必须扩展 Authenticator
类。
Authenticator
类应该定义 name
常量。
Authenticator
通过 Matchers
工作来查找已认证的用户,它将定义的 Matchers
属性与给定的凭证匹配。
<?php namespace App\Http\Authentication\Authenticators; use App\Http\Authentication\Matchers\EmailMatcher; use Raid\Guardian\Authenticators\Authenticator; use Raid\Guardian\Authenticators\Contracts\AuthenticatorInterface; class SystemAuthenticator extends Authenticator implements AuthenticatorInterface { public const NAME = 'system'; protected array $matchers = [ EmailMatcher::class, ]; }
您可以使用两种方式来定义matchers
matchers
属性config\authentication.php
文件
<?php use App\Http\Authentication\Authenticators\SystemAuthenticator; use App\Http\Authentication\Matchers\EmailMatcher; return [ 'authenticator_matchers' => [ SystemAuthenticator::class => [ EmailMatcher::class, ], ], ];
这种定义允许您使用定义的属性通过不同的Matchers
进行用户认证。
Matcher
Matcher
类将用于根据给定的凭据找到已认证的用户。
您可以使用此命令创建一个新的matcher类
php artisan raid:make-matcher EmailMatcher
这将输出以下代码
<?php namespace App\Http\Authentication\Matchers; use Raid\Guardian\Matchers\Matcher; use Raid\Guardian\Matchers\Contracts\MatcherInterface; class EmailMatcher extends Matcher implements MatcherInterface { public const ATTRIBUTE = ''; }
让我们配置Matcher
类。
<?php namespace App\Http\Authentication\Matchers; use Raid\Guardian\Matchers\Matcher; use Raid\Guardian\Matchers\Contracts\MatcherInterface; class EmailMatcher extends Matcher implements MatcherInterface { public const ATTRIBUTE = 'email'; }
Matcher
类必须实现MatcherInterface
。
Matcher
类必须扩展Matcher
类。
Matcher
类必须定义ATTRIBUTE
常量。
Matcher
还可以定义一个QUERY_ATTRIBUTE
常量来查找用户。
ATTRIBUTE
用于将Matcher
与给定的凭据匹配。
QUERY_ATTRIBUTE
被传递给findForAuthentication
方法以查找用户,如果未定义,则将使用ATTRIBUTE
常量。
Norm
Norm
类将用于验证认证。
要应用Norms
,您需要将ShouldRunNorms
接口实现到Authenticator
类,然后您可以定义您的Norms
。
<?php namespace App\Http\Authentication\Authenticators; use App\Http\Authentication\Norms\VerifiedNorm; use Raid\Guardian\Authenticators\Authenticator; use Raid\Guardian\Authenticators\Contracts\AuthenticatorInterface; use Raid\Guardian\Authenticators\Contracts\ShouldRunNorms; class SystemAuthenticator extends Authenticator implements AuthenticatorInterface, ShouldRunNorms { public const NAME = 'system'; protected array $norms = [ VerifiedNorm::class, ]; }
您可以使用两种方式来定义norms
norms
属性config\authentication.php
文件
use App\Http\Authentication\Authenticators\SystemAuthenticator; use App\Http\Authentication\Norms\VerifiedNorm; return [ 'authenticators_norms' => [ SystemAuthenticator::class => [ VerifiedNorm::class, ], ];
Norms
将被应用于Authenticator
以验证认证。
您可以使用此命令创建一个新的规则类
php artisan raid:make-norm VerifiedNorm
这将输出以下代码
<?php namespace App\Http\Authentication\Norms; use Raid\Guardian\Authenticators\Contracts\AuthenticatorInterface; use Raid\Guardian\Norms\Contracts\NormInterface; class VerifiedNorm implements NormInterface { public function handle(AuthenticatorInterface $authenticator): bool { } public function fail(AuthenticatorInterface $authenticator): void { } }
让我们配置Norm
类。
<?php namespace App\Http\Authentication\Norms; use Raid\Guardian\Authenticators\Contracts\AuthenticatorInterface; use Raid\Guardian\Norms\Contracts\NormInterface; class VerifiedNorm implements NormInterface { public function handle(AuthenticatorInterface $authenticator): bool { return $channel->getAuthenticatable()->isVerified(); } public function fail(AuthenticatorInterface $authenticator): void { $channel->fail(message: __('auth.unverified')); } }
Norm
类必须实现NormInterface
。
Norm
类必须定义handle
方法。
handle
方法必须返回一个布尔值。
handle
方法将被Authenticator
调用以验证认证。
Sequence
Sequence
类将用于在认证过程中添加额外的步骤。
要应用Sequences
,您需要将ShouldRunSequences
接口实现到Authenticator
类,然后您可以定义您的Sequences
。
<?php namespace App\Http\Authentication\Authenticators; use App\Http\Authentication\Sequences\TwoFactorEmailSequence; use Raid\Guardian\Authenticators\Authenticator; use Raid\Guardian\Authenticators\Contracts\AuthenticatorInterface; use Raid\Guardian\Authenticators\Contracts\ShouldRunSequences; class SystemAuthenticator extends Authenticator implements AuthenticatorInterface, ShouldRunSequences { public const NAME = 'system'; protected array $sequences = [ TwoFactorEmailSequence::class, ], }
您可以使用两种方式来定义sequences
sequences
属性config\authentication.php
文件
<?php use App\Http\Authentication\Authenticators\SystemAuthenticator; use App\Http\Authentication\Sequences\TwoFactorEmailSequence; return [ 'authenticators_sequences' => [ SystemAuthenticator::class => [ TwoFactorEmailSequence::class, ], ];
Sequences
将被应用于Authenticator
以在认证过程中添加额外的序列。
您可以使用此命令创建一个新的步骤类
php artisan raid:make-sequence TwoFactorEmailSequence
这将输出以下代码
<?php namespace App\Http\Authentication\Sequences; use Raid\Guardian\Authenticators\Contracts\AuthenticatorInterface; use Raid\Guardian\Sequences\Contracts\SequenceInterface; class TwoFactorEmailSequence implements SequenceInterface { public function handle(AuthenticatorInterface $authenticator): void { } }
让我们配置Sequence
类。
<?php namespace App\Http\Authentication\Sequences; use App\Core\Integrations\Mail\MailService; use App\Mail\TwoFactorMail; use Raid\Guardian\Authenticators\Contracts\AuthenticatorInterface; use Raid\Guardian\Sequences\Contracts\SequenceInterface; class TwoFactorEmailStep implements SequenceInterface { public function __construct( private readonly MailService $mailService, ) { } public function handle(AuthenticatorInterface $authenticator): void { $code = generate_code(); $authenticatable = $authenticator->getAuthenticatable(); $authenticatable->update([ 'two_factor_email_code' => $code, ]); $this->send( $authenticatable->getAttribute('email'), $authenticatable->getAttribute('name'), $code, ); } private function send(string $email, string $name, int $code): void { $this->mailService->send( $email, new TwoFactorMail($name, $code), ); } }
Sequence
必须实现SequenceInterface
。
Sequence
类必须定义handle
方法。
handle
方法将被Authenticator
调用以在认证过程中添加额外的序列。
提示:
运行任何步骤意味着Authenticator
将停止认证过程而不会发出任何令牌,此方法可用于多因素
认证。
您可以将您的序列类配置为通过队列工作。
<?php namespace App\Http\Authentication\Sequences; use App\Mail\TwoFactorMail; use App\Core\Integrations\Mail\MailService; use Raid\Guardian\Authenticators\Contracts\AuthenticatorInterface; use Raid\Guardian\Sequences\Contracts\QueueSequenceInterface; class TwoFactorEmailSequence implements QueueSequenceInterface { use HasQueue; public function __construct( private readonly MailService $mailService, ) { } public function handle(AuthenticatorInterface $authenticator): void { $code = generate_code(); $authenticatable = $authenticator->getAuthenticatable(); $authenticatable->update([ 'two_factor_email_code' => $code, ]); $this->send( $authenticatable->getAttribute('email'), $authenticatable->getAttribute('name'), $code, ); } private function send(string $email, string $name, int $code): void { $this->mailService->send( $email, new TwoFactorMail($name, $code), ); } }
队列序列必须实现QueueSequenceInterface
。
队列序列类必须定义queue
方法。
您可以使用HasQueue
特性行为定义带有默认配置的queue
方法。
您可以通过定义以下方法来覆盖特性行为的队列配置
protected function getJob(): string { // return your Job class; } protected function getConnection(): ?string { // return your Connection name; } protected function getQueue(): ?string { // return your Queue name; } protected function getDelay(): DateInterval|DateTimeInterface|int|null { // return your Delay interval; }
认证器错误
您可以使用Authenticator
类通过errors
方法处理认证错误。
您可以使用这些方法向认证器添加错误
$authenticator->fail('key', 'message'); // or $authenticator->errors()->add('key', 'message');
您可以使用这些方法检查认证器错误
$hasErrors = $authenticator->failed(); //or $hasErrors = $authenticator->errors()->any(); $hasError = $authenticator->errors()->has('key'); $errorsByKey = $authenticator->errors()->get('key'); $firstError = $authenticator->errors()->first(); $lastError = $authenticator->errors()->last(); $errorsAsArray = $authenticator->errors()->toArray(); $errorsAsJson = $authenticator->errors()->toJson();
就这些了。
许可
MIT许可证(MIT)。有关更多信息,请参阅许可文件。
鸣谢
安全
如果您发现任何与安全相关的问题,请通过电子邮件而不是使用问题跟踪器。
关于Raid
RAID 是由 Mohamed Khedr 创建的 PHP 框架,并由 Mohamed Khedr 维护。
支持 RAID
RAID 是一个 MIT 许可的开源项目。这是一个独立项目,其持续发展得以实现。