1. 注册认证中间件, 在文件 app/Http/Kernel.php 内完成:
protected $routeMiddleware = [
'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'checkuid' => \App\Http\Middleware\CheckUid::class,
];
 
2. 认证中间件的源码文件:vendor/laravel/framework/src/Illuminate/Auth/Middleware/Authenticate.php 。其中:
 
use Illuminate\Contracts\Auth\Factory as Auth;
public function __construct(Auth $auth)
{
$this->auth = $auth; //Auth 工厂类,这里注入的是 Illuminate\Auth\AuthManager
}
public function handle($request, Closure $next, ...$guards)
{
$this->authenticate($guards);
 
return $next($request);
}
protected function authenticate(array $guards)
{
if (empty($guards)) {//如果没有指定guard 则使用默认
return $this->auth->authenticate(); //通过Illuminate\Auth\AuthManager\__call() 调用 创建guard 实例,并调用guard 实例的 authenticate() 方法进行认证
}
 
foreach ($guards as $guard) {
if ($this->auth->guard($guard)->check()) {//使用指定的guard中第一个能成功认证的
return $this->auth->shouldUse($guard);//将指定guard设置为 本次请求的默认guard。(本次请求后续获取authed user时,都通过这里设置的guard进行)
}
}
 
throw new AuthenticationException('Unauthenticated.', $guards);
}
2.1 $this->auth->authenticate(); //进行身份认证
文件: vendor/laravel/framework/src/Illuminate/Auth/AuthManager.php
public function __call($method, $parameters)
{
return $this->guard()->{$method}(...$parameters);
}
2.2 $this->guard() //获取guard实例
文件: vendor/laravel/framework/src/Illuminate/Auth/AuthManager.php
public function guard($name = null)
{
$name = $name ?: $this->getDefaultDriver();
 
return isset($this->guards[$name])
? $this->guards[$name] //单例
: $this->guards[$name] = $this->resolve($name); //获取 guard 实例
}
public function getDefaultDriver()
{
return $this->app['config']['auth.defaults.guard']; //从配置文件内读取默认guard
}
protected function resolve($name)
{
$config = $this->getConfig($name); //获取指定guard配置信息
 
if (is_null($config)) {
throw new InvalidArgumentException("Auth guard [{$name}] is not defined.");
}
 
if (isset($this->customCreators[$config['driver']])) {//如果设置了自定义工厂,则使用之
return $this->callCustomCreator($name, $config);
}
//类似 createSessionDriver, createTokenDriver 等格式
$driverMethod = 'create'.ucfirst($config['driver']).'Driver';
 
if (method_exists($this, $driverMethod)) {
return $this->{$driverMethod}($name, $config);
}
 
throw new InvalidArgumentException("Auth guard driver [{$name}] is not defined.");
}
 
public function createSessionDriver($name, $config)
{
$provider = $this->createUserProvider($config['provider']);
 
$guard = new SessionGuard($name, $provider, $this->app['session.store']);
 
// When using the remember me functionality of the authentication services we
// will need to be set the encryption instance of the guard, which allows
// secure, encrypted cookie values to get generated for those cookies.
if (method_exists($guard, 'setCookieJar')) {
$guard->setCookieJar($this->app['cookie']);
}
 
if (method_exists($guard, 'setDispatcher')) {
$guard->setDispatcher($this->app['events']);
}
 
if (method_exists($guard, 'setRequest')) {
$guard->setRequest($this->app->refresh('request', $guard, 'setRequest'));
}
 
return $guard;
}
2.3 $this->guard()->authenticate() //使用获取的 guard 实例进行身份认证
文件: vendor/laravel/framework/src/Illuminate/Auth/SessionGuard.php
类中 use 了 GuardHelpers trait
文件:vendor/laravel/framework/src/Illuminate/Auth/GuardHelpers.php
public function authenticate()
{
if (! is_null($user = $this->user())) {
return $user;
}
 
throw new AuthenticationException;
}
文件: vendor/laravel/framework/src/Illuminate/Auth/SessionGuard.php
//此方法是真正进行身份认证的地方!!!!
public function user()
{
if ($this->loggedOut) {
return;
}
 
// If we've already retrieved the user for the current request we can just
// return it back immediately. We do not want to fetch the user data on
// every call to this method because that would be tremendously slow.
if (! is_null($this->user)) {
return $this->user;
}
 
$id = $this->session->get($this->getName()); //从session中获取用户ID。已登录用户的用户ID会被存储在Session内。
 
// First we will try to load the user using the identifier in the session if
// one exists. Otherwise we will check for a "remember me" cookie in this
// request, and if one exists, attempt to retrieve the user using that.
$user = null;
 
if (! is_null($id)) {
if ($user = $this->provider->retrieveById($id)) { //通过Illuminate\Auth\EloquentUserProvider 的retrieveById() 方法,获取用户信息,并返回User Model
$this->fireAuthenticatedEvent($user);
}
}
 
// If the user is null, but we decrypt a "recaller" cookie we can attempt to
// pull the user data on that cookie which serves as a remember cookie on
// the application. Once we have a user we can return it to the caller.
$recaller = $this->getRecaller();//获取认证cookie(登录时选中记住我,服务端会向浏览器设置一个认证cookie,其中包括 remember_token,下次可以直接使用这个认证cookie进行登录)
 
if (is_null($user) && ! is_null($recaller)) {
$user = $this->getUserByRecaller($recaller); //使用 remember_token 从数据库中获取用户信息 (最终是委托 Illuminate\Auth\EloquentUserProvider::retrieveByToken() 方法来取数据)
 
if ($user) {
$this->updateSession($user->getAuthIdentifier()); //将用户ID保存到Session
$this->fireLoginEvent($user, true);
}
}
 
return $this->user = $user;
}

Laravel 5.3 auth中间件底层实现详解的更多相关文章

  1. Laravel 5.3 auth中间件底层实现详解(转)

    1. 注册认证中间件, 在文件 app/Http/Kernel.php 内完成: protected $routeMiddleware = [ 'auth' => \Illuminate\Aut ...

  2. Laravel 5.3 登录注册底层实现详解

          每个控制器都使用 trait 来引入它们需要的方法 */ 用于处理用户登录认证 用于处理新用户注册 包含重置密码逻辑 用于处理重置密码邮件链接   认证需要的视图 包含了应用的基础布局文件 ...

  3. laravel框架的中间件middleware的详解

    本篇文章给大家带来的内容是关于laravel框架的中间件middleware的详解,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. laravel中间件是个非常方便的东西,能将一些逻辑 ...

  4. Spring Aop底层原理详解

    Spring Aop底层原理详解(来源于csdn:https://blog.csdn.net/baomw)

  5. Redis底层函数详解

    Redis底层函数详解 serverCron 函数 它负责管理服务器的资源,并维持服务器的正常运行.在执行 serverCron 函数的过程中会调用相关的子函数,如 trackOperationsPe ...

  6. 线程池底层原理详解与源码分析(补充部分---ScheduledThreadPoolExecutor类分析)

    [1]前言 本篇幅是对 线程池底层原理详解与源码分析  的补充,默认你已经看完了上一篇对ThreadPoolExecutor类有了足够的了解. [2]ScheduledThreadPoolExecut ...

  7. Redis数据类型使用场景及有序集合SortedSet底层实现详解

    Redis常用数据类型有字符串String.字典dict.列表List.集合Set.有序集合SortedSet,本文将简单介绍各数据类型及其使用场景,并重点剖析有序集合SortedSet的实现. Li ...

  8. iptables的概念与底层原理(详解)

    目录 一:iptables 1.iptables简介 2.什么是防火墙? 3.防火墙种类 二:iptables基本介绍 1.解析内容 三:iptables流程(讲解) 1.流入本机 2.解析(流入本机 ...

  9. Express4.x之中间件与路由详解及源码分析

    Application.use() Application.router() express核心源码模拟 一.express.use() 1.1app.use([path,] callback [, ...

随机推荐

  1. spring-aop学习【基于注解】

    我个人觉得,这个好像就是用在定制日志输出上,和log4j很像. 用途: 如果业务方法调用每一步都需要详细的日志,那就用这个吧 好处就是: 方便维护,只包含业务代码 下面开始说明: 所需要的jar包: ...

  2. HDU4787 GRE Words Revenge(AC自动机 分块 合并)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=4787 Description Now Coach Pang is preparing for ...

  3. solr DIH 知识梳理

    solr DIH 知识梳理 web.xml中listener配置 <listener> <listener-class>org.apache.solr.handler.data ...

  4. 总结js的一些复制方法

    1.复制对象: var item1={XXX}; var item2=$.extend(true,{},item1);//深度克隆对象(jQuery方法). lodash也有相关方法:https:// ...

  5. 踏上Salesforce的学习之路(三)

    一.创建Invoice对象 为了使我们的这个Warehouse app更加接近现实,我们现在为他创建一个Invoice对象. 先点击右上角的Setup,然后在左侧的Quick Find查找框中输入Ob ...

  6. Django动态渲染多层菜单

    为后续给菜单设置权限管理方便,通过给页面模版菜单动态渲染,通过数据菜单表进行匹配需要渲染的菜单 #Django表结构 class Menus(models.Model): name = models. ...

  7. Akka-remote使用入门

    在上一篇文章中讲了akka-actor的简单使用,那主要是展现了akka在一台机器上的并发应用,这一篇接着介绍akka-remote使用,简单了解akka在不同机器上的并发应用.我们知道,在一台机器上 ...

  8. python 函数之day3

    一 函数的语法及特性 什么是函数? 定义:函数是一个功能通过一组语句的集合,由名字(函数名)将其封装起来的代码块,要想执行这个函数,只要调用其函数名即可. 特性: 减少重复代码 使程序变的可扩展 使程 ...

  9. IOS UIAlertController 使用方法

    在很多种语言中,alert都表示弹窗操作,弹窗功能非常有用,不仅可以用于正式的app功能中,也可以在调试中使用.在OC中,UIAlertController类用来控制弹窗操作.在IOS 8.0之前, ...

  10. phpstudy虚拟机配置

    PHPStudy是一个常用的PHP本地环境搭建的一个程序包,方便实用.对学习PHP的新手来说, WINDOWS下环境配置是一件很困难的事;对老手来说也是一件烦琐的事.因此无论你是新手还是老手,该程序包 ...