最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 科技 - 知识百科 - 正文

关于Laravel Auth原理浅析

来源:动视网 责编:小采 时间:2020-11-02 18:29:59
文档

关于Laravel Auth原理浅析

关于Laravel Auth原理浅析:下面由Laravel教程栏目给大家介绍Laravel Auth原理浅析,希望对需要的朋友有所帮助!由于公司最近使用Laravel-admin做后台,接触了下Laravel框架,不得不说,Laravel社区的力量以及生态确实挺强大。 但是公司内部业务都处于Java端,后台全部都是调Jav
推荐度:
导读关于Laravel Auth原理浅析:下面由Laravel教程栏目给大家介绍Laravel Auth原理浅析,希望对需要的朋友有所帮助!由于公司最近使用Laravel-admin做后台,接触了下Laravel框架,不得不说,Laravel社区的力量以及生态确实挺强大。 但是公司内部业务都处于Java端,后台全部都是调Jav
下面由Laravel教程栏目给大家介绍Laravel Auth原理浅析,希望对需要的朋友有所帮助!

由于公司最近使用Laravel-admin做后台,接触了下Laravel框架,不得不说,Laravel社区的力量以及生态确实挺强大。

  但是公司内部业务都处于Java端,后台全部都是调JavaApi,因此使用Laravel的特性就得大打折扣了,首先Eloquent模型完全不能用,我这边把业务分开来,只存了3张表,这是Laravel-admin自带的表。

企业微信截图_15967872395039.png

  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;
 }

第一次写文,有错误请指出谢谢!

文档

关于Laravel Auth原理浅析

关于Laravel Auth原理浅析:下面由Laravel教程栏目给大家介绍Laravel Auth原理浅析,希望对需要的朋友有所帮助!由于公司最近使用Laravel-admin做后台,接触了下Laravel框架,不得不说,Laravel社区的力量以及生态确实挺强大。 但是公司内部业务都处于Java端,后台全部都是调Jav
推荐度:
标签: 原理 浅谈 laravel
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top