让用户和客户端共享相同的身份验证
Let Users and Clients share the same authentication
我正在使用 Laravel + Breeze。我的应用程序将有两个访问站点:
- 管理员可以登录相关用户table(工作中)
- 客户端可以登录相关客户端table(待讨论)
我不知道,这是否是个好主意,但我想与另一个模型:clients 共享已经实现的 Auth 服务。
我已经实现的是:
- 登录用户可以创建客户端
- 客户收到来自活动的电子邮件验证电子邮件
- 客户端可以确认电子邮件地址,并将重定向到登录视图
现在对我来说变得棘手了。 AuthenticatedSessionController::store()
方法正在检查 $request->authenticate()
,这会再次对用户 table 运行,但对客户端 table 失败。
我稍微修改了根据登录候选类型重定向的方法:
public function store(LoginRequest $request)
{
$request->authenticate();
$request->session()->regenerate();
$user = User::where('id', Auth::id())->first();
if ( $user ) {
return redirect()->intended(RouteServiceProvider::HOME);
}
$client = Client::where('id', Auth::id())->findOrFail();
if ( $client ) {
return redirect()->to('portal.show', $client->id);
}
}
但这仅适用于用户,因为 $request->authenticate()
不会让客户进入。
现在我需要支持,从这里开始我只是猜测下一步是我在 config/auth.php
:
中所做的更新
return [
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
'clients' => [
'driver' => 'eloquent',
'model' => App\Models\Client::class,
],
],
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_resets',
'expire' => 60,
'throttle' => 60,
],
'clients' => [
'provider' => 'clients',
'table' => 'password_resets',
'expire' => 60,
'throttle' => 60,
],
],
'password_timeout' => 10800,
];
您需要研究并修改 App\Http\Requests\Auth\LoginRequest
class 的 authenticate
方法。
一种方法是检查是否存在通过针对 users
和 clients
table 的请求收到的 email
。
然后,如果 电子邮件 属于客户端 - 实施自定义逻辑以根据 clients
table 记录验证凭据并登录客户端
并且如果 电子邮件 属于用户 - 然后让请求正常通过
例如:
public function authenticate()
{
$type = DB::table('clients')->where('email', $this->email)->exists() ? 'client' : 'user';
if($type === 'user') {
return $this->authenticateUser();
}
//Validate credentials against `clients` table
// If valid retrieve the client and login the client
//Else throw ValidationException
}
//Copy the content of original authenticate to this method
protected function authenticateUser()
{
$this->ensureIsNotRateLimited();
if (! Auth::attempt($this->only('email', 'password'), $this->boolean('remember'))) {
RateLimiter::hit($this->throttleKey());
throw ValidationException::withMessages([
'email' => trans('auth.failed'),
]);
}
RateLimiter::clear($this->throttleKey());
}
注意 使用这种方法你不会做任何rate-limiting/throttling也不会触发尝试事件
对于完整的客户端身份验证系统,我想需要定义一个单独的守卫、用户提供者,然后重新定义 re-implement SessionGuard
功能。
想到的另一个疯狂的想法是,为什么不将 Client 表示为 users
table 上的记录,仅用于身份验证目的,并且可能它们之间有 one-to-one 关系。
我正在使用 Laravel + Breeze。我的应用程序将有两个访问站点:
- 管理员可以登录相关用户table(工作中)
- 客户端可以登录相关客户端table(待讨论)
我不知道,这是否是个好主意,但我想与另一个模型:clients 共享已经实现的 Auth 服务。
我已经实现的是:
- 登录用户可以创建客户端
- 客户收到来自活动的电子邮件验证电子邮件
- 客户端可以确认电子邮件地址,并将重定向到登录视图
现在对我来说变得棘手了。 AuthenticatedSessionController::store()
方法正在检查 $request->authenticate()
,这会再次对用户 table 运行,但对客户端 table 失败。
我稍微修改了根据登录候选类型重定向的方法:
public function store(LoginRequest $request)
{
$request->authenticate();
$request->session()->regenerate();
$user = User::where('id', Auth::id())->first();
if ( $user ) {
return redirect()->intended(RouteServiceProvider::HOME);
}
$client = Client::where('id', Auth::id())->findOrFail();
if ( $client ) {
return redirect()->to('portal.show', $client->id);
}
}
但这仅适用于用户,因为 $request->authenticate()
不会让客户进入。
现在我需要支持,从这里开始我只是猜测下一步是我在 config/auth.php
:
return [
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
'clients' => [
'driver' => 'eloquent',
'model' => App\Models\Client::class,
],
],
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_resets',
'expire' => 60,
'throttle' => 60,
],
'clients' => [
'provider' => 'clients',
'table' => 'password_resets',
'expire' => 60,
'throttle' => 60,
],
],
'password_timeout' => 10800,
];
您需要研究并修改 App\Http\Requests\Auth\LoginRequest
class 的 authenticate
方法。
一种方法是检查是否存在通过针对 users
和 clients
table 的请求收到的 email
。
然后,如果 电子邮件 属于客户端 - 实施自定义逻辑以根据 clients
table 记录验证凭据并登录客户端
并且如果 电子邮件 属于用户 - 然后让请求正常通过
例如:
public function authenticate()
{
$type = DB::table('clients')->where('email', $this->email)->exists() ? 'client' : 'user';
if($type === 'user') {
return $this->authenticateUser();
}
//Validate credentials against `clients` table
// If valid retrieve the client and login the client
//Else throw ValidationException
}
//Copy the content of original authenticate to this method
protected function authenticateUser()
{
$this->ensureIsNotRateLimited();
if (! Auth::attempt($this->only('email', 'password'), $this->boolean('remember'))) {
RateLimiter::hit($this->throttleKey());
throw ValidationException::withMessages([
'email' => trans('auth.failed'),
]);
}
RateLimiter::clear($this->throttleKey());
}
注意 使用这种方法你不会做任何rate-limiting/throttling也不会触发尝试事件
对于完整的客户端身份验证系统,我想需要定义一个单独的守卫、用户提供者,然后重新定义 re-implement SessionGuard
功能。
想到的另一个疯狂的想法是,为什么不将 Client 表示为 users
table 上的记录,仅用于身份验证目的,并且可能它们之间有 one-to-one 关系。