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

问题描述 投票:0回答:6

在构建我的应用程序时,我通过运行

php artisan make:auth
使用了 Laravel 身份验证脚手架,这非常棒,节省了我很多时间。

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

例如,使用

[email protected]
注册的用户无法使用
[email protected]
登录。

我从我的研究中了解到,技术上@之前的部分是区分大小写的,因为规范的优点,并且从理论上讲,上面的两封电子邮件可能属于两个不同的人。但在我的情况下,我预计我需要在登录时强制执行此操作的可能性不大。

我正在使用 Postgres 数据库,因此如果可能的话,我希望将

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

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

解决方案

我最终通过首先采纳 @btl 建议并在电子邮件属性上实现一个 mutator 方法来解决这个问题。我不想检查并更改现有用户的所有电子邮件,并且感觉如果我确实遇到了我想要恢复区分大小写的问题,我想要一个可以的解决方案很容易被撤消。

应用程序/User.php

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

应用程序/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 authentication laravel-5 laravel-5.5
6个回答
10
投票

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

public function setEmailAttribute($value)
{
    $this->attributes['email'] = strtolower($value);
}

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

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

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

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


3
投票

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

 $credentials = ['email' => '[email protected]', '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
     }
 }

0
投票

@btl 答案很完美,但还有另一种方法。

您可以编辑注册控制器。

应用程序/Http/Controller/Auth/RegisterController.php

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

0
投票

我想保留数据库中指定的大小写(在我的例子中是用户名)。我能找到的唯一方法是重写 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);

0
投票

我解决了 LoginController 中的 ovveriding 凭证功能

function credentials(Request $request)
{
    return ["email"=> strtolower($request->email), "password"=> request('password')];
}

0
投票

首先,创建您的自定义提供程序:

use Illuminate\Auth\EloquentUserProvider;

class CaseInsensitiveUserProvider extends EloquentUserProvider
{
    public function retrieveByCredentials(array $credentials)
    {
        $query = $this->newModelQuery();
        return $query->where('email', 'ilike', $credentials['email']);
    }
}

然后,在 AppServiceProvider.php 的

boot
方法中将其设置为名为“eloquent-ci”的自定义身份验证提供程序:

$this->app->get('auth')->provider('eloquent-ci', function ($app, $config) {
    return new CaseInsensitiveUserProvider($app['hash'], $config['model']);
});

在 config/auth.php 中,将 eloquent 重命名为 eloquent-ci:

'providers' => [
    'users' => [
        'driver' => 'eloquent-ci',
        'model' => App\Models\User::class,
    ],
© www.soinside.com 2019 - 2024. All rights reserved.