// 使用下面这个命令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;
}
原文链接:https://juejin.im/entry/5959f64e6fb9a06bb4747c41

laravel5.8 Auth::guide的更多相关文章

  1. laravel5通过auth.attempt事件加入登陆验证码

    <?php namespace WangDong\Http\Controllers\Auth; use Illuminate\Http\Exception\HttpResponseExcepti ...

  2. laravel5.5 调用系统自带登陆认证auth

    1执行命令 php artisan make:auth 2 编辑文件 config/auth guardes 'admin' => [ 'driver' => 'session', 'pr ...

  3. laravel5.8ajax请求auth认证返回302的解决方法。

    注册 /app/Http/Controller/Auth/RegisterController.php <?php namespace App\Http\Controllers\Auth; us ...

  4. Send Push Notifications to iOS Devices using Xcode 8 and Swift 3, APNs Auth Key

    Send Push Notifications to iOS Devices using Xcode 8 and Swift 3 OCT 6, 2016 Push notifications are ...

  5. Laravel5.0学习--02 实例进阶

    本文以laravel5.0.22为例. 本节以新建一个简单的博客作为实例. 准备工作 数据库配置 .env文件(也可以直接修改config/database.php) DB_HOST=localhos ...

  6. Laravel5.0学习--01 入门

    本文以laravel5.0.22为例. 生产环境建议使用laravel5.1版本,因为该版本是长期支持版本.5.1文档更详细:http://laravel-china.org/docs/5.1. 环境 ...

  7. Linux搭建smtp服务器+laravel5.2发邮件配置

    /** * 这里主要是想通过自己搭建smtp服务器,配置laravel5.2框架,实现邮箱发邮件功能, * 主要内容是搭建smtp服务器,laravel5.2发邮件顺手提一下 */ /** * 1.l ...

  8. xmemcached user guide --存档

    XMemcached Introduction XMemcached is a new java memcached client. Maybe you don't know "memcac ...

  9. Laravel5中集成Jasig cas统一认证系统

    CAS : CAS(Central Authentication Service)是一款不错的针对 Web 应用的单点登录框架,这里介绍下我刚在laravel5上搭建成功的cas.提前准备工作:可运行 ...

随机推荐

  1. 如何消除 com.netflix.discovery.shared.transport.TransportException: Cannot execute request on any known server

    在application.properties中添加以下两句话: eureka.client.register-with-eureka=falseeureka.client.fetch-registr ...

  2. slub

    1.前言 在Linux中,伙伴系统(buddy system)是以页为单位管理和分配内存.但是现实的需求却以字节为单位,假如我们需要申请20Bytes,总不能分配一页吧!那岂不是严重浪费内存.那么该如 ...

  3. Oracle非分区索引,全局分区索引和本地分区索引。

    1.如果按照索引是否分区作为划分依据,Oracle 的索引类型可以分为非分区索引,全局分区索引和本地分区索引. 2.创建演示实例 --创建非分区表create table test_partition ...

  4. 64位编译器下,将指针转换成UINT32,不需要修改编译选项的编码方式

    一些严格的64位编译器,将指针转换成UINT32,会报各种丢失精度的错误. 但很显然,有些时候,我们就是需要转换,且并不会真正丢失精度. 此时不需要修改编译选项的编码方式,有些用处了 示例如下: un ...

  5. JS实战篇

    实现选项卡的选择: 效果图如下: 代码如下: <!DOCTYPE html> <html> <head> <meta charset="UTF-8& ...

  6. java:Hibernate框架4(延迟加载(lazy),抓取(fetch),一级缓存,get,load,list,iterate,clear,evict,flush,二级缓存,注解,乐观锁和悲观锁,两者的比较)

    1.延时加载和抓取: hibernate.cfg.xml: <?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE hibernate-co ...

  7. select去掉默认样式

    今天遇到的问题,并在这里做一下记录和总结 去除select下拉框默认样式 select { /*Chrome和Firefox里面的边框是不一样的,所以复写了一下*/ border: solid 1px ...

  8. Python学习之数据库初识

    9 数据库 9.1 数据库的初识 ​ 数据库是可以独立运行的,并且可以对数据的增删改查提供高效便捷方式的工具. 数据库解决的问题: ​ 解决了操作文件的效率和便捷问题 ​ 解决了多个服务同时使用数据时 ...

  9. DHCP迁移

    情况1:windows 2003迁移到windows 2003或者windows 2008,按照需要以下几个步骤:1.在源DHCP服务器导出DHCP数据文件,执行以下命令netsh dhcp serv ...

  10. vue父子组件相互传值的实例

    当子组件需要向父组件传递数据时,就要用到自定义事件 子组件用 $emit()来触发事件,父组件用$on()来监昕子组件的事件 父组件也可以直接在子组件的自定义标签上使用 v-on 来监昕子组件触发的自 ...