[教程] Laravel 认证:同一个登录框内提供「用户名或邮箱」登录?

Laravel

一个小技巧分享给大家。Laravel 默认的身份验证允许使用一个 email 字段登录。但也可同时使用 username 等类似的其他字段。Laravel 默认使用一个字段登录时只能用 email,但是我们也可以只使用 username来登录。

在本教程中,我们将看到如何只使用两个字段—— login 和 password 来登录。login 既可以是 email 也可以是 username。

让我们来创建允许你使用 email 或 uername 两者之一来登录的 Laravel 项目。

设置项目

首先使用laravel installer创建一个名为login的新laravel项目。我们将在本教程中使用laravel 5.6。

laravel new login

.env 文件中设置数据库配置.

运行以下命令以支持基本登录和注册。

php artisan make:auth

打开database/migrations目录中的create_users_table.php。 在up中添加用户名字段以存储用户名。 为此,请复制下面的代码并替换up方法。

public function up()
{
    Schema::create('users', function (Blueprint $table) {
        $table->increments('id');
        $table->string('name');
        $table->string('username');
        $table->string('email')->unique();
        $table->string('password');
        $table->rememberToken();
        $table->timestamps();
    });
}

现在,通过运行以下命令来迁移数据库。

php artisan migrate

注册用户

在数据库中添加用户名字段后,还需要更改Laravel默认注册页面以接受用户名并将其保存在数据库中。

注册页面

首先,让我们在用户注册表单中添加用户名输入的文本框。转到 resources/views/auth 目录中的 register.blade.php 。在名称行后添加以下代码以添加用户名输入字段的文本框。

<div class="form-group row">
    <label for="username" class="col-md-4 col-form-label text-md-right">
        {{ __('Username') }}
    </label>

    <div class="col-md-6">
        <input id="username" type="text"
               class="form-control{{ $errors->has('username') ? ' is-invalid' : '' }}"
               name="username" value="{{ old('username') }}" required>

        @if ($errors->has('username'))
            <span class="invalid-feedback">
                <strong>{{ $errors->first('username') }}</strong>
            </span>
        @endif
    </div>
</div>

上面的代码非常简单。 我刚刚复制了Name输入框并使用username更改了属性。

register.blade.php的完整代码

注册控制器

前端设置完成之后只剩下后端后端逻辑。 打开 app/Http/Controllers/Auth 目录下的 RegisterController.php 文件。

validator 方法中,为username字段添加验证。下面这是编写过后的代码。

protected function validator(array $data)
{
    return Validator::make($data, [
        'name' => 'required|string|max:255',
        'username' => 'required|string|max:255|unique:users',
        'email' => 'required|string|email|max:255|unique:users',
        'password' => 'required|string|min:6|confirmed',
    ]);
}

用户名是必须的,需要一个字符串,最多包含255个字符,并且在users表中的username字段中是唯一的。

create 方法中, 添加username字段,让username和其他字段一起保存到数据库中。下面是编写过后的 create 方法。

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

现在我们已经在注册流程中设置了username字段。

使用用户名或邮件登录

现在,在注册用户时添加了用户名。 让用户可以使用电子邮件或用户名登录。

登录页面

首先,我们需要对登录页面进行一些修改,尤其是在邮件地址的输入框。
打开 resources/views/auth 目录下的 login.blade.php 文件。现在替换表单中的邮件地址输入框的内容替换为下面的内容。

<div class="form-group row">
    <label for="login" class="col-sm-4 col-form-label text-md-right">
        {{ __('Username or Email') }}
    </label>

    <div class="col-md-6">
        <input id="login" type="text"
               class="form-control{{ $errors->has('username') || $errors->has('email') ? ' is-invalid' : '' }}"
               name="login" value="{{ old('username') ?: old('email') }}" required autofocus>

        @if ($errors->has('username') || $errors->has('email'))
            <span class="invalid-feedback">
                <strong>{{ $errors->first('username') ?: $errors->first('email') }}</strong>
            </span>
        @endif
    </div>
</div>

别担心,我将解释上面的代码。基本上我们使用表单中的 login 发送用户输入的内容。Laravel会接收它,并且知道它是邮件还是用户名。它在请求中既可以代表邮件也可以代表用户名。所以,在 input 标签中的 value 属性中,如果 old('username') 或者 old('email') 其中的一个存在值就设置它。

检查错误时我们也是这样做的。 如果用户名或邮件位于errors数组中,我们会输出相应的错误。

login.blade.php的完整代码

登录控制器

让我们为登录设置后端逻辑. 打开 app/Http/Controllers/Auth 目录下的 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';

    /**
     * Login username to be used by the controller.
     *
     * @var string
     */
    protected $username;

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

        $this->username = $this->findUsername();
    }

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

        $fieldType = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'username';

        request()->merge([$fieldType => $login]);

        return $fieldType;
    }

    /**
     * Get username property.
     *
     * @return string
     */
    public function username()
    {
        return $this->username;
    }
}

让我解释一下登录控制器中的每个更改。我们添加了一个新的用户名属性,我们将用它来存储登录字段是电子邮件或者用户名。 此字段只有两个值电子邮件或用户名。在构造函数中,我们调用 findUsername 方法。 在这个方法中,我们得到 login 输入的值。我们检查该字段是有效的电子邮件,如果是,我们将 $ fieldType 设置为 email 否则为 username 。然后我们使用 merge() 方法在请求中添加带有输入 login$ fieldTypemerge() 方法基本上将新输入合并到当前请求的数组中。 然后我们返回$ fieldType,它可以是emailusername

我们在类中添加的最后一个方法是username方法。 此方法覆盖了laravel用于获取要使用的登录用户名的 username 方法。

这就是在一个字段中使用电子邮件或用户名登录所需的全部内容。

在以下位置找到项目的完整源代码 GitHub.


Practice makes perfect.

原文地址:https://tutsforweb.com/laravel-auth-logi...

译文地址:https://learnku.com/laravel/t/27889

《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 7

这个能使用电子邮箱和用户名登录,如果加上电话号码呢?怎么区分 fieldType?

2个月前 评论

@Evan 那你就只能限制用户名的逻辑 不允许存数字账号 这样的话用正则判断出是不是纯数字就能区别开了

2个月前 评论
likunyan

嗯,文章这个适合个人用。

一般都有手机了,手机登录很常见。所以登录时,直接以name=登录方式比较好用点。jQuery、Vue或 React 直接切换。

2个月前 评论

我加了正则判断手机号码

if (filter_var($username, FILTER_VALIDATE_EMAIL)) {
    $fieldType = 'email';
} elseif (preg_match("/^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$/", $username)) {
    $fieldType = 'mobile';
} else {
    $fieldType =  'name';
}
2个月前 评论

@Evan 你如果用户注册的地方不做限制 用户恶意注册手机号段的账号 你就麻烦了
@lovecn
另外 推荐个正则表达式

2个月前 评论

如果用户的名字叫做某个别人的手机号可咋整。。。

2周前 评论

请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!

社区文档:

将托管在 packagist.org 和 github.com 的扩展包使用国内 CDN 加速
GitHub Laravel 扩展包 TOP 250
速查表方便快速查询框架功能,支持手机访问,支持中英文版本
Laravel 中文文档,由社区用户翻译和维护,将会保持一直更新
此文档的目的,就是为了提高技术团队的凝聚力、一致性和生产效率。
开发环境的部署,开发者工具的选择,适用于 Mac 和 Windows。
浓缩过后的精华
Laravel Nova 后台管理面板文档的中文翻译
Lumen 中文文档,由社区用户翻译和维护,将会保持一直更新
Laravel 下知名扩展包 Dingo API 的中文文档,Laravel API 开发必知必会