您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關Laravel Auth原理的示例分析的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
由于公司最近使用Laravel-admin做后臺,接觸了下Laravel框架,不得不說,Laravel社區的力量以及生態確實挺強大。
但是公司內部業務都處于Java端,后臺全部都是調JavaApi,因此使用Laravel的特性就得大打折扣了,首先Eloquent模型完全不能用,我這邊把業務分開來,只存了3張表,這是Laravel-admin自帶的表。
Laravel-admin帶了9張表,由于用戶登錄業務全保存在Api端,自帶的表功能被我割舍了。因此需要自己實現Api登錄的邏輯,而又必須走Laravel Auth認證。
原理解讀
// 使用下面這個命令Laravel會自動為我們生成Auth路由和認證模塊。跟著代碼往下解讀。 php artisan make:auth // Http/Controllers/Auth/LoginController 使用了 AuthenticatesUsers
其中 下面這三個方法詮釋了登錄邏輯的全部。
public function login(Request $request) { $this->validateLogin($request); if ($this->hasTooManyLoginAttempts($request)) { $this->fireLockoutEvent($request); return $this->sendLockoutResponse($request); } // 這里嘗試登錄系統, if ($this->attemptLogin($request)) { return $this->sendLoginResponse($request); } $this->incrementLoginAttempts($request); return $this->sendFailedLoginResponse($request); } protected function attemptLogin(Request $request) { return $this->guard()->attempt( $this->credentials($request), $request->has('remember') ); } protected function guard() { return Auth::guard(); }
控制器會去尋找Auth::guard(), 那這個Auth::guard()是個什么東西呢,
首先 Auth 是系統的單例,原型在
Illuminate\Auth\AuthManager;
顧名思義,是一個Auth管理模塊,實現了認證工廠模式接口guards(),
public function __construct($app) { $this->app = $app; $this->userResolver = function ($guard = null) { return $this->guard($guard)->user(); }; } // Auth::guard();就是調用了這個方法。 public function guard($name = null) { // 首先查找$name, 沒有就使用默認的驅動, $name = $name ?: $this->getDefaultDriver(); // 意思就是要實例化出這個驅動并且返回, return isset($this->guards[$name]) ? $this->guards[$name] : $this->guards[$name] = $this->resolve($name); } // 默認的驅動是從配置文件里面讀取的,/config/auth.php default配置項 public function getDefaultDriver() { return $this->app['config']['auth.defaults.guard']; } // 這里是構造Auth-guard驅動 protected function resolve($name) { $config = $this->getConfig($name); if (is_null($config)) { throw new InvalidArgumentException("xxx"); } // 這里是如果你自己實現的驅動就返回 if (isset($this->customCreators[$config['driver']])) { return $this->callCustomCreator($name, $config); } // 這里是系統默認兩個類分別是 // session 和 token 這里主要講 sessionGuard . $driverMethod = 'create'.ucfirst($config['driver']).'Driver'; if (method_exists($this, $driverMethod)) { return $this->{$driverMethod}($name, $config); } throw new InvalidArgumentException("xxx"); }
接下來看看配置文件 auth.php
// Auth::guard() ,不傳參數,就調用默認的default.guard , 'defaults' => [ 'guard' => 'web', 'passwords' => 'users', ], // 系統的guard .默認支持 "database", "eloquent",意思就是說你的provider必須是這兩個實例中的一個, 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'token', 'provider' => 'users', ], ], // 這個就是上面的provider了,你使用哪一個provider作為你的Auth::guard()返回的 // 模型 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\User::class, ], // 'users' => [ // 'driver' => 'database', // 'table' => 'users', // ], ],
也就是說終歸到底,Auth::guard(), 在默認配置里面是給我反回了一個sessionGuard .
主要看下面4個方法
namespace Illuminate\Auth; class SessionGuard{ public function attempt(array $credentials = [], $remember = false) { // 這里觸發 試圖登錄事件,此時還沒有登錄 $this->fireAttemptEvent($credentials, $remember); $this->lastAttempted = $user = $this->provider->retrieveByCredentials($credentials); // 這里會調用hasValidCredentials,其實就是驗證用戶名和密碼的一個過程 if ($this->hasValidCredentials($user, $credentials)) { // 如果驗證通過了,就調用login方法 . $this->login($user, $remember); return true; } // 否則就觸發登錄失敗事件,返回假 $this->fireFailedEvent($user, $credentials); return false; } // 這里是登錄用戶的操作,就是說調用這個方法已經是合法用戶了,必須是一個 // AuthenticatableContract 的實例 . public function login(AuthenticatableContract $user, $remember = false) { // 直接更新session,這里就是把session存起來,session的鍵在該方法的 // getName() 里邊, $this->updateSession($user->getAuthIdentifier()); if ($remember) { $this->ensureRememberTokenIsSet($user); $this->queueRecallerCookie($user); } // 觸發登錄事件,已經登錄了這個時候, $this->fireLoginEvent($user, $remember); // 將user對象保存到sessionGuard , 后續的類訪問Auth::user();直接拿到 $this->setUser($user); } // 這里就是經常使用到的 Auth::user()了,具體如何返回看AuthManager里面的 // __call public function user() { if ($this->loggedOut) { return; } if (! is_null($this->user)) { return $this->user; } // 這里讀取session拿到user的id , $id = $this->session->get($this->getName()); $user = null; // 如果拿到了id ,查找到該user if (! is_null($id)) { if ($user = $this->provider->retrieveById($id)) { $this->fireAuthenticatedEvent($user); } } $recaller = $this->recaller(); if (is_null($user) && ! is_null($recaller)) { $user = $this->userFromRecaller($recaller); if ($user) { $this->updateSession($user->getAuthIdentifier()); $this->fireLoginEvent($user, true); } } return $this->user = $user; } // 這里就直接返回用戶id了, public function id() { if ($this->loggedOut) { return; } return $this->user() ? $this->user()->getAuthIdentifier() : $this->session->get($this->getName()); } }
大體上用戶登錄的流程就完了,簡單過程就是
//偽代碼 $credentials = $request()->only(['username' ,'password']); if(Auth::guard("session")->attempt($credentials)){ // 登錄成功 }else{ // 登錄失敗 }
實現用戶登錄之后才能訪問的控制器/方法
Route::get("/home")->middleware("auth"); // auth Middleware 是在app/Http/Kernel中注冊的, // 類名是 \Illuminate\Auth\Middleware\Authenticate::class // 解析過程實質上是這個方法: public function handle($request, Closure $next, ...$guards) { $this->authenticate($guards); return $next($request); } protected function authenticate(array $guards) { // 默認情況下會去 Auth中尋找authenticate這個方法 if (empty($guards)) { return $this->auth->authenticate(); } // 如果middleware中傳了參數,會遍歷一遍,不通過就拋出異常 foreach ($guards as $guard) { if ($this->auth->guard($guard)->check()) { return $this->auth->shouldUse($guard); } } throw new AuthenticationException('Unauthenticated.', $guards); } //sessionGuard 中的authenticate其實也就是調用了一遍user方法。 public function authenticate() { if (! is_null($user = $this->user())) { return $user; } throw new AuthenticationException; }
感謝各位的閱讀!關于“Laravel Auth原理的示例分析”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。