Laravel: 如何在登录时检查一个额外的字段,除了电子邮件和密码?

Laravel: how to check an extra field while logging in, in addition to email and password?

我希望我的用户在访问网站之前验证他们的电子邮件地址。

我认为没有预建系统,所以我向我的用户 table.

添加了一个 enabled 布尔字段,默认为 false

我该如何处理?

我在这里查看源代码:https://github.com/laravel/framework/blob/5.5/src/Illuminate/Foundation/Auth/AuthenticatesUsers.php#L74-L79

/**
 * Attempt to log the user into the application.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return bool
 */
protected function attemptLogin(Request $request)
{
    return $this->guard()->attempt(
        $this->credentials($request), $request->filled('remember')
    );
}
/**
 * Get the needed authorization credentials from the request.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return array
 */
protected function credentials(Request $request)
{
    return $request->only($this->username(), 'password');
}

我想覆盖 guard 的 'attempt' 方法...但我不知道什么是 'guard'(我保证会提供文档)并且在哪里/如何覆盖或扩展或实施以检查启用的字段

编辑

我找到了这个文档:https://laravel.com/docs/5.5/authentication#authenticating-users

我真的不明白这个方法的调用是从哪里来的……以及如何填充 $email$password 变量……无论如何我试过了,但是我一无所获。没有错误,但即使已启用设置为 false,用户也会登录。请注意,我的 'username' 字段几乎是 'username'。我没有使用电子邮件字段。

public function authenticate()
{
    if (Auth::attempt(['username' => $username, 'password' => $password, 'enabled' => true])) 
    {
        // Authentication passed...
        return redirect($this->redirectTo());
    }
}

public function username()
{
    return 'username';
}

I want my users validate their email address before the can access to website.

  • 您可以只使用 laravel 的 Auth::attempt() 来使用 email 登录用户。如需更多信息,visit this link.

注意:如果你还想传递其他字段,你可以这样做:

Auth::attempt(['email' => $request->input('email'), 'enabled' => 1]);

我找到了一个行之有效的解决方案

在我的 LoginController.php 中,我重写了特征 AuthenticatesUsers; 中的两个函数。

请注意,第二次覆盖只是覆盖给用户的消息。

/**
 * Attempt to log the user into the application.
 * NOTE: this override DO NOT uses at all the trait version
 * See: https://laravel.com/docs/5.5/authentication#authenticating-users
 *
 * @param  \Illuminate\Http\Request  $request
 * @return bool
 */
protected function attemptLogin(Request $request)
{
    return Auth::attempt(
        $this->credentials($request) + ["enabled" => true],
        $request->filled('remember')
    );
}

/**
 * Get the failed login response instance.
 * NOTE: this override DO NOT uses at all the trait version
 *
 * @param  \Illuminate\Http\Request  $request
 * @return \Symfony\Component\HttpFoundation\Response
 *
 * @throws ValidationException
 */
protected function sendFailedLoginResponse(Request $request)
{
    throw ValidationException::withMessages([
        $this->username() => [trans('auth.failed_or_account_not_activated')],
    ]);
}

我添加一些解释。

关于attemptLogin

框架的默认实现是

    return $this->guard()->attempt(
        $this->credentials($request), $request->filled('remember')
    );

attempt 接受一个数组作为第一个参数用于凭证,一个布尔值作为第二个参数,意思是“记住用户登录”

credentials函数实现为

protected function credentials(Request $request)
{
    return $request->only($this->username(), 'password');
}

在我的实现中,我没有传递用户名和密码,而是传递

$this->credentials($request) + ["enabled" => true],

所以我传递了 3 个字段而不是一个;我通过了

array [ 'username', 'password', 'enabled' ]

框架将在内部为具有给定用户名、密码和启用字段值的用户查找数据库。

关于sendFailedLoginResponse

此覆盖仅用于向用户显示更准确的错误消息。因为在这种情况下,用户可以拥有正确的用户名和密码,但无法启用 he/she。

所以我不想出现可能具有误导性的错误,例如 "wrong user credentials', but a more contextualized " 错误的用户凭据或未激活的帐户。

默认sendFailedLoginResponse实现是

    throw ValidationException::withMessages([
        $this->username() => [trans('auth.failed')],
    ]);

我只是要求 Laravel 发送不同的字符串

throw ValidationException::withMessages([
    $this->username() => [trans('auth.failed_or_account_not_activated')],
]);

要翻译的字符串必须放入resources/lang/<lang_code>/auth.php

我在默认值附近添加了一个字符串翻译

'failed' => 'Le credenziali inserite non corrispondono a nessun utente',

我加了

'failed_or_account_not_activated' => "Le credenziali inserite non corrispondono a nessun utente oppure l'account non è stato ancora attivato",