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路由和认证模块。跟着代码往下解读。
phpartisanmake:auth

//Http/Controllers/Auth/LoginController 使用了 AuthenticatesUsers

其中 下面这三个方法诠释了登录逻辑的全部。

publicfunctionlogin(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);
}
protectedfunctionattemptLogin(Request$request)
{
return$this->guard()->attempt(
$this->credentials($request),$request->has('remember')
);
}
protectedfunctionguard()
{
returnAuth::guard();
}

控制器会去寻找Auth::guard(), 那这个Auth::guard()是个什么东西呢,

首先 Auth 是系统的单例,原型在

Illuminate\Auth\AuthManager;

顾名思义,是一个Auth管理模块,实现了认证工厂模式接口guards(),

publicfunction__construct($app)
{
$this->app=$app;
$this->userResolver=function($guard=null){
return$this->guard($guard)->user();
};
}
//Auth::guard();就是调用了这个方法。
publicfunctionguard($name=null)
{
//首先查找$name,没有就使用默认的驱动,
$name=$name?:$this->getDefaultDriver();
//意思就是要实例化出这个驱动并且返回,
returnisset($this->guards[$name])
?$this->guards[$name]
:$this->guards[$name]=$this->resolve($name);
}
   
//默认的驱动是从配置文件里面读取的,/config/auth.php default配置项
publicfunctiongetDefaultDriver()
{
return$this->app['config']['auth.defaults.guard'];
}
  
  //这里是构造Auth-guard驱动
  protectedfunctionresolve($name)
{
$config=$this->getConfig($name);
if(is_null($config)){
thrownewInvalidArgumentException("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);
}
thrownewInvalidArgumentException("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个方法

namespaceIlluminate\Auth;
classSessionGuard{
publicfunctionattempt(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);
returntrue;
}
//否则就触发登录失败事件,返回假
$this->fireFailedEvent($user,$credentials);
returnfalse;
}
//这里是登录用户的操作,就是说调用这个方法已经是合法用户了,必须是一个
  //AuthenticatableContract的实例.
publicfunctionlogin(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
publicfunctionuser()
{
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了,
publicfunctionid()
{
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");
//authMiddleware是在app/Http/Kernel中注册的,
//类名是\Illuminate\Auth\Middleware\Authenticate::class
//解析过程实质上是这个方法:
publicfunctionhandle($request,Closure$next,...$guards)
{
$this->authenticate($guards);
return$next($request);
}

protectedfunctionauthenticate(array$guards)
{
//默认情况下会去Auth中寻找authenticate这个方法
if(empty($guards)){
return$this->auth->authenticate();
}
//如果middleware中传了参数,会遍历一遍,不通过就抛出异常
foreach($guardsas$guard){
if($this->auth->guard($guard)->check()){
return$this->auth->shouldUse($guard);
}
}
thrownewAuthenticationException('Unauthenticated.',$guards);
}
//sessionGuard中的authenticate其实也就是调用了一遍user方法。
publicfunctionauthenticate()
{
if(!is_null($user=$this->user())){
return$user;
}
thrownewAuthenticationException;
}

感谢各位的阅读!关于“Laravel Auth原理的示例分析”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

发布于 2021-03-13 15:39:47
收藏
分享
海报
0 条评论
166
上一篇:Laravel8有哪些新变化 下一篇:php实现四则运算的方法
目录

    0 条评论

    本站已关闭游客评论,请登录或者注册后再评论吧~

    忘记密码?

    图形验证码