如何使用 Laravel 5.5 身份验证使电子邮件登录不区分大小写

Posted

技术标签:

【中文标题】如何使用 Laravel 5.5 身份验证使电子邮件登录不区分大小写【英文标题】:How to make email login case insensitive with Laravel 5.5 authentication 【发布时间】:2018-07-05 04:35:54 【问题描述】:

在构建我的应用程序时,我通过运行php artisan make:auth 使用了 Laravel 身份验证脚手架,这非常棒,为我节省了很多时间。

但是,我遇到了用户无法登录的问题,因为他们不记得最初注册时用于电子邮件的情况。

例如,使用Myemail@domain.com 注册的用户无法使用myemail@domain.com 登录。

我从我的研究中了解到,技术上virtue of the spec 之前的部分是区分大小写的,并且上面的两封电子邮件理论上可能属于两个不同的人。不过,在我的情况下,我不认为有足够的可能性需要在登录时强制执行此操作。

我正在使用 Postgres 数据库,因此我希望尽可能将 Auth::attempt() 中的电子邮件数据库查找替换为 ilike 而不是 like。但是,我一生都无法找到它在源代码中的位置,因此不知道我将如何覆盖它。

Tl;dr 我如何覆盖 Laravel 的默认身份验证以不区分大小写的方式进行电子邮件查找?

解决方案

我最终解决了这个问题,首先接受@btl 建议并在 email 属性上实现一个 mutator 方法。我不想为现有用户检查并更改所有电子邮件,并且觉得如果我遇到了想要恢复区分大小写的问题,我想要一个可以轻松撤消。

app/User.php

public function getEmailAttribute($value) 
    return strtolower($value);

app/Http/Controllers/Auth/LoginController.php

protected function credentials()

    $username = $this->username();
    $credentials = request()->only($username, 'password');
    if (isset($credentials[$username])) 
        $credentials[$username] = strtolower($credentials[$username]);
    
    return $credentials;

不幸的是,我不知道如何将相同的逻辑应用于ForgotPasswordController.php,但现在我会活下去。现在无论电子邮件情况如何,登录似乎都可以正常工作。

【问题讨论】:

我只是尝试使用随机大小写的电子邮件登录我所有的 Laravel 应用程序,并且每次都有效。我认为它不应该区分大小写。 @jeff 我也不会这么认为,但由于某种原因,在 Laravel 5.5 中,我在几个实例中遇到了这个问题。 【参考方案1】:

在您的用户模型上添加一个 mutator 方法以使电子邮件全部小写:

public function setEmailAttribute($value)

    $this->attributes['email'] = strtolower($value);

每当用户注册时,电子邮件将始终转换为小写。

或者,在用户模型上使用访问器:

public function getEmailAttribute($value)

    return strtolower($value);

这样原始值会保留在数据库中,但每当您调用 $user->email 时,它将是小写的。在进行严格比较时,您只需要将用户在登录时的输入转换为小写即可。

【讨论】:

但是如果用户现在尝试使用大写电子邮件地址登录会发生什么?我的猜测是他收到了“无效的凭据”,这让用户非常困惑。 我同意西蒙的观点。您将让用户创建帐户或拥有现有帐户,但现在他们不知道如何登录,因为他们的电子邮件大小写已更改。验证器中的唯一检查需要不区分大小写。 Accessor 方法很棒,不会影响我的应用程序上的注册/登录。原因是 Eloquent 搜索对我来说似乎不区分大小写,而像 firstWhere() 这样的其他收集方法是。【参考方案2】:

您也可以进行自定义尝试。

 $credentials = ['email' => 'useremail@gmail.com', 'psasword' => 1234];

 public function checkAttempt($credentials)
 
     $user = UserTable::whereRaw('lower(email) = ? ', [$credentials['email']])->firstorFail();

     $validPassword = Hash::check($credentials['password'], $user->password;

     if ($user  && $validPassword)
     
        // set user session over here
     
 

【讨论】:

【参考方案3】:

@btl Answers 是完美的,但还有另一种方法。

您可以编辑寄存器控制器。

App/Http/Controller/Auth/RegisterController.php

protected function create(array $data)

   return User::create([
       'name' => $data['name'],
       'email' => strtolower($data['email']),
       'password' => bcrypt($data['password']),
   ]);

【讨论】:

【参考方案4】:

我想保持它在数据库中指定的方式(在我的情况下是用户名)。我能找到的唯一方法是覆盖 UserProvider (特别是 retrieveByCredentials 部分)。这对于看似简单的改变来说是相当麻烦的。最后,我没有使用 Auth::attempt 方法,而是通过手动检索用户、检查密码、然后使用 Auth::login 方法解决了这个问题:

$user = User::where('username', 'ilike', $req->input('username'))->first();

if (!$user ||
    !Hash::check($req->input('password'), $user->password)
) 
    return response()->json(['status' => 'FAILED']);

Auth::login($user);

【讨论】:

【参考方案5】:

我解决了 LoginController 中的过度验证凭据功能

function credentials(Request $request)

    return ["email"=> strtolower($request->email), "password"=> request('password')];

【讨论】:

以上是关于如何使用 Laravel 5.5 身份验证使电子邮件登录不区分大小写的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 5.5 无法使用身份验证脚手架登录

Laravel 5.5 - 升级身份验证后没有正确重定向

为 JWTAuth 身份验证 Laravel 5.5 指定除默认值之外的其他守卫/提供者

Laravel身份验证 - 不同表格中的电子邮件

Laravel 5.5登录后重定向到特定路由

laravel 5.5 内置鉴权数据库表参考位置