学习笔记《Laravel Auth 代码阅读》

Laravel 官方提供了一个完整的权限验证模块,通过阅读这个小系统的代码,可以一窥 Laravel 的核心设计机制

安装

官方有详细的这个模块的使用文档:
https://laravel.com/docs/5.5/authentication

安装方式:artisan make:auth

生成一个 Middleware 文件:

app/Http/Middleware/RedirectIfAuthenticated.php

和四个 Controller 文件:

app/Http/Controllers/Auth/ForgotPasswordController.php
app/Http/Controllers/Auth/LoginController.php
app/Http/Controllers/Auth/RegisterController.php
app/Http/Controllers/Auth/ResetPasswordController.php

然后在 app/Http/Kernel.php 中完成对中间件的注册:

'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, // 在这行注册
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,

代码阅读

中间件 RedirectIfAuthenticated.php 代码不多,核心代码是:

Auth::guard($guard)->check()

你会发现其实 Auth(Illuminate\Support\Facades\Auth) 类并没有 guard() 这个方法,而是调用基类 Facade 中的 __callStatic() 方法来间接调用名为 'auth' 的 Service Container,官方文档中有几者之间的对应关系,以及所指向的入口文件:

根据上面的对应关系,会激活这个类:Illuminate\Auth\AuthManager 然后调用里面的 guard() 方法:

public function guard($name = null)
{
    $name = $name ?: $this->getDefaultDriver();

    return isset($this->guards[$name])
                ? $this->guards[$name]
                : $this->guards[$name] = $this->resolve($name);
}

上面的代码主要是为了选定好 guard 然后返回(guard 是 Laravel 的权限设定机制,默认是 web+session,你可以通过设置 config/auth.php 中的配置项来使用自定义的 guard)

再看一眼本文开始的这行代码:

Auth::guard($guard)->check()

在选定好 guard 以后,调用 guard 的 check() 方法,代码可以在 GuardHelpers.php 里面找到:

/**
 * Determine if the current user is authenticated.
 *
 * @return bool
 */
public function check()
{
    return ! is_null($this->user());
}

如果你用的是 Session,那么判断用户登录状态的代码会在这个位置:
/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());

    // 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.
    if (! is_null($id)) {
        if ($this->user = $this->provider->retrieveById($id)) {
            $this->fireAuthenticatedEvent($this->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->recaller();

    if (is_null($this->user) && ! is_null($recaller)) {
        $this->user = $this->userFromRecaller($recaller);

        if ($this->user) {
            $this->updateSession($this->user->getAuthIdentifier());

            $this->fireLoginEvent($this->user, true);
        }
    }

    return $this->user;
}

Auth 路由注册

在 /routes/web.php 中轻飘飘的写了一句 Auth::routes(); 实际上完成了 Auth 相关的一些路由注册,位置在 /Illuminate/Routing/Router.php 内容为

public function auth()
{
    // Authentication Routes...
    $this->get('login', 'Auth\LoginController@showLoginForm')->name('login');
    $this->post('login', 'Auth\LoginController@login');
    $this->post('logout', 'Auth\LoginController@logout')->name('logout');

    // Registration Routes...
    $this->get('register', 'Auth\RegisterController@showRegistrationForm')->name('register');
    $this->post('register', 'Auth\RegisterController@register');

    // Password Reset Routes...
    $this->get('password/reset', 'Auth\ForgotPasswordController@showLinkRequestForm')->name('password.request');
    $this->post('password/email', 'Auth\ForgotPasswordController@sendResetLinkEmail')->name('password.email');
    $this->get('password/reset/{token}', 'Auth\ResetPasswordController@showResetForm')->name('password.reset');
    $this->post('password/reset', 'Auth\ResetPasswordController@reset');
}

关于 Facade

Facade 是一套配合 Service Container 的静态方法解决方案,是一套设计得非常优雅的机制,是 Laravel 的核心机制之一:

Facades provide a "static" interface to classes that are available in the application's service container. Laravel ships with many facades which provide access to almost all of Laravel's features. Laravel facades serve as "static proxies" to underlying classes in the service container, providing the benefit of a terse, expressive syntax while maintaining more testability and flexibility than traditional static methods.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容

  • 先说几句废话,调和气氛。事情的起由来自客户需求频繁变更,伟大的师傅决定横刀立马的改革使用新的框架(created ...
    wsdadan阅读 3,033评论 0 12
  • 过去做事情急,什么东西拿起来就用,不喜欢进行系统性的学习,造成在使用过程中的错误和低效,现在感觉自己耐心多了,用之...
    马文Marvin阅读 1,964评论 0 10
  • 一直有个写作梦,没想到在无限拖延后今日终于有勇气落笔了。我即将迈入30岁,怎么都没想到会已失业的状态迎接这...
    悦猫儿阅读 708评论 0 0
  • 今天第三次来到深圳 哥哥有了嫂子,我暂时住在这里,心情负责,和哥哥用方言交流我觉得是不尊重嫂子的表现,因为她听不懂...
    梦婆故事吧阅读 289评论 0 0
  • 忆春风,浅堤沙白,婀娜垂落青柳。 清明前后梨花树,碧绿附门环扣。 连雨久。 夜黯黯,窗纱犹卧新虫瘦。 孤灯对酒。 ...
    文轩阁阁主阅读 181评论 0 3