Laravel默认只允许用户使用其电子邮件地址登录。现在,如果要让您的用户使用电子邮件甚至用户名登录,该怎么办?

为此,您只需要更改Laravel默认身份验证代码中的某些代码即可。

开始吧。我认为您已经设置了Laravel项目并迁移了Laravel默认身份验证。如果您还没有编写命令php artisan make:auth,那么请执行php artisan migrate

上面的命令使Laravel为您提供基本和默认身份验证,因此您不必手动制作登录,注册,忘记密码和重置密码。

步骤

打开loginController.php
默认情况下,您只会在登录控制器中看到这些代码

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;

class LoginController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Login Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles authenticating users for the application and
    | redirecting them to your home screen. The controller uses a trait
    | to conveniently provide its functionality to your applications.
    |
    */

    use AuthenticatesUsers;

    /**
     * Where to redirect users after login.
     *
     * @var string
     */
    protected $redirectTo = '/home';

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest')->except('logout');
    }
}

该控制器仅具有属性和一个构造函数,那么它如何处理登录功能?在这里OOP发挥作用。

注意这里的use AuthenticatesUsers;声明,这是Laravel构建其默认登录功能的地方。现在,让我们检查一下AuthenticateUsers类。

<?php

namespace Illuminate\Foundation\Auth;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\ValidationException;

trait AuthenticatesUsers
{
    use RedirectsUsers, ThrottlesLogins;

    /**
     * Show the application's login form.
     *
     * @return \Illuminate\Http\Response
     */
    public function showLoginForm()
    {
        return view('auth.login');
    }

    /**
     * Handle a login request to the application.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\Response|\Illuminate\Http\JsonResponse
     *
     * @throws \Illuminate\Validation\ValidationException
     */
    public function login(Request $request)
    {
        $this->validateLogin($request);

        // If the class is using the ThrottlesLogins trait, we can automatically throttle
        // the login attempts for this application. We'll key this by the username and
        // the IP address of the client making these requests into this application.
        if (method_exists($this, 'hasTooManyLoginAttempts') &&
            $this->hasTooManyLoginAttempts($request)) {
            $this->fireLockoutEvent($request);

            return $this->sendLockoutResponse($request);
        }

        if ($this->attemptLogin($request)) {
            return $this->sendLoginResponse($request);
        }

        // If the login attempt was unsuccessful we will increment the number of attempts
        // to login and redirect the user back to the login form. Of course, when this
        // user surpasses their maximum number of attempts they will get locked out.
        $this->incrementLoginAttempts($request);

        return $this->sendFailedLoginResponse($request);
    }

    /**
     * Validate the user login request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return void
     *
     * @throws \Illuminate\Validation\ValidationException
     */
    protected function validateLogin(Request $request)
    {
        $request->validate([
            $this->username() => 'required|string',
            'password' => 'required|string',
        ]);
    }

    /**
     * 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');
    }

    /**
     * Send the response after the user was authenticated.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    protected function sendLoginResponse(Request $request)
    {
        $request->session()->regenerate();

        $this->clearLoginAttempts($request);

        return $this->authenticated($request, $this->guard()->user())
                ?: redirect()->intended($this->redirectPath());
    }

    /**
     * The user has been authenticated.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  mixed  $user
     * @return mixed
     */
    protected function authenticated(Request $request, $user)
    {
        //
    }

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

    /**
     * Get the login username to be used by the controller.
     *
     * @return string
     */
    public function username()
    {
        return 'email';
    }

    /**
     * Log the user out of the application.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function logout(Request $request)
    {
        $this->guard()->logout();

        $request->session()->invalidate();

        return $this->loggedOut($request) ?: redirect('/');
    }

    /**
     * The user has logged out of the application.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return mixed
     */
    protected function loggedOut(Request $request)
    {
        //
    }

    /**
     * Get the guard to be used during authentication.
     *
     * @return \Illuminate\Contracts\Auth\StatefulGuard
     */
    protected function guard()
    {
        return Auth::guard();
    }
}

如果您是初学者,并且刚接触OOP世界,那么在看这些代码行时,您可能会觉得不知所措。但是不要。现在,我们在处理登录功能的类中进行了查看,现在您的问题可能是“我们如何自定义它以满足我们的需求?”

好吧,你不!请记住,“ AuthenticateUsers”类的位置Illuminate\Foundation\Auth\AuthenticatesUsersVendor目录下。不要编辑或更改此类中的任何内容,否则您的Composer会感到烦恼!

Laravel是一个Object-Oriented框架。因此,我们正在应用重写的OOP方法。

我们希望我们的应用程序允许用户使用电子邮件或用户名登录,因此让我们看一下处理该部分内容的方法AuthenticateUsers。您可能已经注意到,此方法username()描述了它的作用。

/**
* Get the login username to be used by the controller.
*
* @return string
*/
public function username()
{
    return 'email';
}

上面的注释告诉我们,它将email作为控制器使用的登录用户名返回。现在,这是我们必须重写的方法。

复制该username()方法并将其粘贴到您的计算机中loginController.php。现在,代替返回email,我们需要返回emailusername

现在这是我们必须检查登录表单的部分。在我们的默认登录表单中,查找默认的电子邮件输入,并将名称从更改name="email"name="identity"。稍后,它将identity作为HTTP请求发送到我们的Laravel。

再次回到username()方法,我们需要实现一种方法来检查email以电子邮件地址或用户名形式出现的HTTP请求。我们可以通过检查发送的数据中是否有“ @”来做到这一点。幸运的是,PHP建立了一个函数来执行此操作。如果有一个“ @”,则HTTP请求email确实是一个电子邮件地址。否则,它是一个用户名。

/**
* Get the login username to be used by the controller.
*
* @return string
*/
public function username()
{
     $login = request()->input('identity');

     $field = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'username';
     request()->merge([$field => $login]);

     return $field;
}

上面的代码的作用是使用来过滤出现@或电子邮件的HTTP请求FILTER_VALIDATE_EMAIL。如果是电子邮件,则返回email,否则,返回username

完成此操作后,我们只剩下一个要做的事情,那就是覆盖验证请求。在您的登录控制器类中,在下面添加以下代码:

/**
     * Validate the user login request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return void
     *
     * @throws \Illuminate\Validation\ValidationException
     */
    protected function validateLogin(Request $request)
    {
        $messages = [
            'identity.required' => 'Email or username cannot be empty',
            'email.exists' => 'Email or username already registered',
            'username.exists' => 'Username is already registered',
            'password.required' => 'Password cannot be empty',
        ];

        $request->validate([
            'identity' => 'required|string',
            'password' => 'required|string',
            'email' => 'string|exists:users',
            'username' => 'string|exists:users',
        ], $messages);
    }

默认验证仅检查电子邮件,现在我们将其更改为检查电子邮件和用户名。

现在,您有了一个可行的解决方案,可以让您的用户使用电子邮件地址或用户名登录。

如果您有任何疑问,请告诉我:)

via https://dev.to/pramanadiputra/laravel-how-to-let-user-login-with-email-or-username-j2h

最后更新于 2020年8月29日

Laravel:如何让用户使用电子邮件或用户名登录
标签: