最近在一個項目中須要實現一個多字段登陸功能,就是能夠使用用戶名、郵箱或手機號任意一種方式進行登陸。php
如下內容基於laravel5.4laravel
首先,經過artisan
工具生成auth模塊數據庫
php artisan make:auth
app
這時候App\Http\Controllers
目錄下會新增一個Auth
目錄,該目錄下爲註冊登陸相關的控制器,resources\views
目錄下也會生成一些與註冊登陸相關的視圖工具
laravel的官方文檔中說手動認證用戶須要使用Illuminate\Support\Facades\Auth
類的attempt方法,以下:測試
<?php namespace App\Http\Controllers; use Illuminate\Support\Facades\Auth; class LoginController extends Controller { /** * Handle an authentication attempt. * * @return Response */ public function authenticate() { if (Auth::attempt(['email' => $email, 'password' => $password])) { // Authentication passed... return redirect()->intended('dashboard'); } } }
這個方法會根據你傳入的參數判斷數據庫中是否存在與之相匹配的用戶,若是存在而且密碼正確返回true
,反之返回false
this
遂在LoginController
中添加該方法,可是好像並無效果spa
因而開始觀察LoginController
的實現機制,發現它實現了一個AuthenticatesUsers
的trait
,追蹤到這個trait
的定義文件,發現這個文件就是咱們想要的東西code
裏面有一個login
方法,就是負責處理登陸的邏輯orm
/** * Handle a login request to the application. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\Response */ 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. // 防止暴力破解,屢次登陸失敗會根據IP鎖定 if ($this->hasTooManyLoginAttempts($request)) { $this->fireLockoutEvent($request); return $this->sendLockoutResponse($request); } // 這個就是主要的負責判斷數據庫中是否存在相應的帳號和密碼的地方,咱們須要重寫的就是attemptLogin方法 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); }
分析了一波這個文件,發現主要進行登陸判斷的就是attemptLogin
方法,咱們只要重寫這個方法便可,先看看原來的是怎麼寫的,根據原來的進行重寫:
/** * 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->has('remember') ); }
在LoginController重寫後:
public function attemptLogin(Request $request) { $username = $request->input('username'); $password = $request->input('password'); // 驗證用戶名登陸方式 $usernameLogin = $this->guard()->attempt( ['username' => $username, 'password' => $password], $request->has('remember') ); if ($usernameLogin) { return true; } // 驗證手機號登陸方式 $mobileLogin = $this->guard()->attempt( ['mobile' => $username, 'password' => $password], $request->has('remember') ); if ($mobileLogin) { return true; } // 驗證郵箱登陸方式 $emailLogin = $this->guard()->attempt( ['email' => $username, 'password' => $password], $request->has('remember') ); if ($emailLogin) { return true; } return false; }
只須要用attempt
方法進行屢次判斷便可,只要成功就返回true
,不成功繼續用其餘字段進行判斷,都不成功則返回flase
測試,能夠實現多字段登陸效果