關于Laravel Auth原理淺析

下面由laravel教程欄目給大家介紹laravel auth原理淺析,希望對需要的朋友有所幫助!

關于Laravel Auth原理淺析

由于公司最近使用Laravel-admin做后臺,接觸了下Laravel框架,不得不說,Laravel社區的力量以及生態確實挺強大。

  但是公司內部業務都處于Java端,后臺全部都是調JavaApi,因此使用Laravel的特性就得大打折扣了,首先Eloquent模型完全不能用,我這邊把業務分開來,只存了3張表,這是Laravel-admin自帶的表。

關于Laravel Auth原理淺析

  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 是系統的單例,原型在

IlluminateAuthAuthManager;

顧名思義,是一個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'?=>?AppUser::class, ????????], ????????//?'users'?=>?[ ????????//?????'driver'?=>?'database', ????????//?????'table'?=>?'users', ????????//?], ????],

也就是說終歸到底,Auth::guard(), 在默認配置里面是給我反回了一個sessionGuard .

主要看下面4個方法

namespace?IlluminateAuth; 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中注冊的, //?類名是??IlluminateAuthMiddlewareAuthenticate::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; ????}

第一次寫文,有錯誤請指出謝謝!

? 版權聲明
THE END
喜歡就支持一下吧
點贊8 分享