Laravel - 使用用户名、电子邮件或电话号码登录

10

我已经在我的现有项目中实现了用户名或电子邮件登录,并且运行良好。我想将其扩展为使用用户名、电子邮件或电话登录。我希望用户可以使用用户名、电子邮件或电话号码和密码进行登录。

这是我的代码: App\Http\Controllers\Auth\LoginController

<?php

namespace App\Http\Controllers\Auth;
use Socialite;

use Illuminate\Http\Request;
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');
    }

    /**
     * Redirect the user to the GitHub authentication page.
     *
     * @return \Illuminate\Http\Response
     */
      public function redirectToProvider($social)
      {
          return Socialite::driver($social)->redirect();
      }

      /**
       * Obtain the user information from GitHub.
       *
       * @return \Illuminate\Http\Response
       */
      public function handleProviderCallback($social)
      {
          $user = Socialite::driver($social)->user();

          // $user->token;
      }
      /**
       * Get the needed authorization credentials from the request.
       *
       * @param  \Illuminate\Http\Request  $request
       * @return array
       */
        protected function credentials(Request $request)
        {
            $field = filter_var($request->get($this->username()), FILTER_VALIDATE_EMAIL)
                ? $this->username()
                : 'username';

            return [
                $field => $request->get($this->username()),
                'password' => $request->password,
            ];
        }
}

App\Http\Controllers\Auth\RegisterController

<?php

namespace App\Http\Controllers\Auth;

use App\User;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;

class RegisterController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Register Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles the registration of new users as well as their
    | validation and creation. By default this controller uses a trait to
    | provide this functionality without requiring any additional code.
    |
    */

    use RegistersUsers;

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

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

    /**
     * Get a validator for an incoming registration request.
     *
     * @param  array  $data
     * @return \Illuminate\Contracts\Validation\Validator
     */
    protected function validator(array $data)
    {
        return Validator::make($data, [
            'name' => 'required|string|max:255',
            'username' => 'required|string|max:20|unique:users',
            'phone' => 'required|string|max:20|unique:users',
            'email' => 'required|string|email|max:255|unique:users',
            'password' => 'required|string|min:6|confirmed',
            'gender' => 'required|bool',
        ]);
    }

    /**
     * Create a new user instance after a valid registration.
     *
     * @param  array  $data
     * @return \App\User
     */
    protected function create(array $data)
    {
        if($data['gender'])
          {
            $avatar = 'default/avatars/male.png';
          }
        else
          {
            $avatar = 'default/avatars/female.png';
          }
        return User::create([
            'name' => $data['name'],
            'gender' => $data['gender'],
            'username' => $data['username'],
            'phone' => $data['phone'],
            'email' => $data['email'],
            'password' => bcrypt($data['password']),
            'slug' => str_slug($data['username']),
            'avatar' => $avatar,
        ]);
    }
}

注册功能正常,我能够将用户电话存储到用户表中。我已经在 views/auth/login.php 文件中将电子邮件的输入类型更改为文本,并且可以使用用户名或电子邮件登录。

当我在 LoginController 中将用户名更改为电话号码时,无法使用电话号码进行登录,因为它会显示“在 App\Http\Controllers\Auth\LoginController 上不存在 [phone] 方法”。

当我添加一个方法时

/**
     * Create a new controller instance.
     *
     * @return void
     */
public function phone()
    {
      return 'phone';
    }
/**
       * Get the needed authorization credentials from the request.
       *
       * @param  \Illuminate\Http\Request  $request
       * @return array
       */
        protected function credentials(Request $request)
        {
            $field = filter_var($request->get($this->phone()), FILTER_VALIDATE_EMAIL)
                ? $this->phone()
                : 'phone';

            return [
                $field => $request->get($this->phone()),
                'password' => $request->password,
            ];
        }

无法使用手机登录。出现错误提示:这些凭据与我们的记录不符。还尝试了以下操作。

/**
       * Get the needed authorization credentials from the request.
       *
       * @param  \Illuminate\Http\Request  $request
       * @return array
       */
        protected function credentials(Request $request)
        {
            if(is_numeric($request->get('email'))){
              return ['phone'=>$request->get('email'),'password'=>$request->get('password')];
            }
            return $request->only($this->username(), 'password'); 
        }

我现在可以用电话或电子邮件登录,但无法使用用户名登录。 如何实现使用用户名、电子邮件或电话号码登录


你是使用单一字段进行登录,可以使用用户名、电子邮件或电话号码,对吗? - Raza Mehdi
@RazaMehdi 我尝试了一下,现在我可以使用电话或电子邮件登录。但是我不知道如何通过单个输入实现任意三种方式(电话、电子邮件、用户名)的登录。请检查上面更新的代码。 - user6780526
兄弟,我只是给你举了一个例子。你需要建立规则来确定什么样的输入才是有效的电话号码、用户名或密码。在这种情况下,你可能需要添加自己的身份验证函数。 - Raza Mehdi
1
你不需要按照@RazaMehdi所说的去做,那太复杂了。只需尝试以每种类型登录即可,不必担心传递给你的内容。 - Ohgodwhy
@Ohgodwhy 在 laracasts 上展示了我的代码,miiikkeyyyy 在一秒钟内进行了修正,现在它可以正常工作。我会发布这段代码。 - user6780526
显示剩余3条评论
4个回答

32
这段代码可行。希望能对某些人有所帮助。
protected function credentials(Request $request)
        {
          if(is_numeric($request->get('email'))){
            return ['phone'=>$request->get('email'),'password'=>$request->get('password')];
          }
          elseif (filter_var($request->get('email'), FILTER_VALIDATE_EMAIL)) {
            return ['email' => $request->get('email'), 'password'=>$request->get('password')];
          }
          return ['username' => $request->get('email'), 'password'=>$request->get('password')];
        }

如果是数字,使用数字登录。如果是电子邮件,则使用电子邮件地址登录。否则尝试使用用户名登录。
最终的LoginController如下所示。
<?php

namespace App\Http\Controllers\Auth;
use Socialite;

use Illuminate\Http\Request;
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');
    }

    /**
     * Redirect the user to the GitHub authentication page.
     *
     * @return \Illuminate\Http\Response
     */
      public function redirectToProvider($social)
      {
          return Socialite::driver($social)->redirect();
      }

      /**
       * Obtain the user information from GitHub.
       *
       * @return \Illuminate\Http\Response
       */
      public function handleProviderCallback($social)
      {
          $user = Socialite::driver($social)->user();

          // $user->token;
      }

      /**
       * Get the needed authorization credentials from the request.
       *
       * @param  \Illuminate\Http\Request  $request
       * @return array
       */
        protected function credentials(Request $request)
        {
          if(is_numeric($request->get('email'))){
            return ['phone'=>$request->get('email'),'password'=>$request->get('password')];
          }
          elseif (filter_var($request->get('email'), FILTER_VALIDATE_EMAIL)) {
            return ['email' => $request->get('email'), 'password'=>$request->get('password')];
          }
          return ['username' => $request->get('email'), 'password'=>$request->get('password')];
        }
}

这非常有帮助,你帮我省了很多事。 - Ngugi Kiarie

16

这段代码适用于Laravel 7

步骤1 -- 在LoginController类中添加username方法

public function username()
{
    $login = request()->input('username');

    if(is_numeric($login)){
        $field = 'phone';
    } elseif (filter_var($login, FILTER_VALIDATE_EMAIL)) {
        $field = 'email';
    } else {
        $field = 'username';
    }

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

    return $field;
}

第二步 -- 在LoginController类中添加sendFailedLoginResponse方法

protected function sendFailedLoginResponse(Request $request)
{
    throw ValidationException::withMessages([
        'username' => [trans('auth.failed')],
    ]);
}

最终的LoginController如下所示

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;

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 = RouteServiceProvider::HOME;

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

    /**
     * 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([
            'username' => [trans('auth.failed')],
        ]);
    }

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

        if(is_numeric($login)){
            $field = 'phone';
        } elseif (filter_var($login, FILTER_VALIDATE_EMAIL)) {
            $field = 'email';
        } else {
            $field = 'username';
        }

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

        return $field;
    }
}

第三步 -- 编辑视图login.blade.php -> 登录表单

  • 将name从"name = email"更改为"name = username"
  • 将错误消息从电子邮件更改为用户名
@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Login') }}</div>

                <div class="card-body">
                    <form method="POST" action="{{ route('login') }}">
                        @csrf

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

                            <div class="col-md-6">
                                <input id="username" type="text" class="form-control @error('username') is-invalid @enderror" name="username" value="{{ old('username') }}" required autofocus>

                                @error('username')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>

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

                            <div class="col-md-6">
                                <input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="current-password">

                                @error('password')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>

                        <div class="form-group row">
                            <div class="col-md-6 offset-md-4">
                                <div class="form-check">
                                    <input class="form-check-input" type="checkbox" name="remember" id="remember" {{ old('remember') ? 'checked' : '' }}>

                                    <label class="form-check-label" for="remember">
                                        {{ __('Remember Me') }}
                                    </label>
                                </div>
                            </div>
                        </div>

                        <div class="form-group row mb-0">
                            <div class="col-md-8 offset-md-4">
                                <button type="submit" class="btn btn-primary">
                                    {{ __('Login') }}
                                </button>

                                @if (Route::has('password.request'))
                                    <a class="btn btn-link" href="{{ route('password.request') }}">
                                        {{ __('Forgot Your Password?') }}
                                    </a>
                                @endif
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection


1
顺便说一句,除了“username()”检查和电子邮件输入类型为“text”之外,您不需要进行任何其他更改。 - ctf0

1

使用电子邮件手机号码用户名登录,请尝试以下方法...

if(Auth::attempt(['phone' => request('phone'), 'password' => request('password')]) ||
Auth::attempt(['email' => request('email'), 'password' => request('password')]) ||
Auth::attempt(['name' => request('name'), 'password' => request('password')])){
    // do something ...
}

您也可以添加自定义检查字段,例如 "Active"='1',如下所示:Auth::attempt(['name' => request('name'), 'password' => request('password'), 'Active' => '1'])


0

文件地址:vendor/laravel/ui/auth-backend/AuthenticatesUsers.php

protected function credentials(Request $request)
    {

        if (is_numeric($request->get('email'))) {
            return ['mobile' => $request->get('email'), 'password' => $request->get('password')];
        } elseif (filter_var($request->get('email'), FILTER_VALIDATE_EMAIL)) {
            return ['email' => $request->get('email'), 'password' => $request->get('password')];
        }

        return $request->only($request->get('email'), 'password');
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接