解决 csrf_field () 渲染后_token 的 value 为空的问题

前言

  • 平时我们在使用csrf_field()或者csrf_token()来进行表单验证时,绝对总是一马平川,没有任何悬念可言。也就从来没把它太当回事。

  • 之前项目都是用的laravel5.1 LTS版本的,所以登录,验证之类的基本都非常ok,需要多权限就直接采用"kbwebs/multiauth": "~1.0"这个插件包处理。也没有在csrf身上花费过多的时间。

  • 当前项目用5.3版,之前的multiauth支持方面感觉不是特别好了,同时也发现5.3自带这样的功能。就进行尝试和折腾(当然,基本都是采用下班时间做研究,不然白天工作没产出怎么对得起老板啊!在研究的同时,也喜欢做些记录,这也是上班期间无法细致做到的地方。)

  • Providers/RouteServiceProvider.php和config/auth.php文件中配置好对应内容(详情参见:“[https://learnku.com/articles/5489/larval-53-multi-authority-login-correct-position](Laravel 5.3 自带多权限登录正确姿势))

  • 刷新登录页面http://xxxx.app/admin/login,会发现首当其冲的会出现这个问题:

    Undefined variable: errors (View: /home/vagrant/Codes/kejisi/resources/views/admin/auth/login.blade.php)
  • 经查证资料,发现是缺少\Illuminate\View\Middleware\ShareErrorsFromSession::class这个中间件的验证,导致$error变量无法被识别;

  • 这时,就想到新建一个新项目,采用 php artisan make:Auth命令,看看自带的权限认证是怎么样一个流程,再来对比分析来拍错。它会自动生成路由:

    Auth::routes();
    Route::get('/home', 'HomeController@index');
    Auth::routes();
    Route::get('/home', 'HomeController@index');
  • 这些路由都是直接在web.php中生成,但是我想要的是所有与后台相关的路由会自动转发到route/admin.app,通过观察Auth生成的路由好像起不到作用(算是我们分析中走了一点弯路吧)。

  • 好吧,我们再想想,既然你能将路由拆分到不同的文件中,你就必须要知道为什么这样拆分,拆分后laravel是怎么去识别哪个路由能转发到哪个路由文件中:

    routes
    ├── admin.php
    ├── api.php
    └── web.php
  • 这时就会马上想到在Providers/RouteServiceProvider.php文件中做过分类操作,
    一般情况我们会有默认生成好的方法:

    protected function mapWebRoutes()
    {
        Route::group([
            'middleware' => 'web',
            'namespace'  => $this->namespace,
        ], function ($router) {
            require base_path('routes/web.php');
        });
    }
  • 这里面的web其实就对应着\App\Http\Kernel中的路由中间件分组web,同时也会把对应的路由转发到routes/web.php中,可以发现在这里面有一个\App\Http\Middleware\VerifyCsrfToken::class这个不就是进行csrf验证的吗?

  • 好,既然如此,我们在kernel.php从新建立一个路由分组,直接对应后台的操作做验证,是否可行呢?
    于是我们可以在进行以下2步操作:

  • 1,$middlewareGroups中加入:

    'admin' => [
        这里可以添加我们需要的各种中间件
    ]

    此时,我们再次刷新登录页面http://xxxx.app/admin/login,会发现

    Session store not set on request.

    说明缺少Seesion相关中间件支持,在middlewareGroups中的admin加上\Illuminate\Session\Middleware\StartSession::class

    接着又出现下面问题:
    Undefined variable: errors (View: /home/vagrant/Codes/kejisi/resources/views/admin/auth/login.blade.php)

    这个问题依然存在。于是经过多方资料查证,发现是缺少\Illuminate\View\Middleware\ShareErrorsFromSession::class中间件。会导致$error变量无法被识别和解析。

  • 这时我们会发现已经可以看到久违的登录界面了。

  • 但是进行登录时,始终会出现不管怎样始终无法登进行验证通过,查看页面源代码发现,_token的值居然为空,也就是我们标题中所提到的问题,有且仅有一个地方出现了,那就是在登录这个页面。其他页面的表现就如同之前5.1中一样的行云流水,一马平川。在这里始终无法进入后台。

  • 再加上\App\Http\Middleware\VerifyCsrfToken::class,看看。终于可以正常登录了。
    但是此时,其实我们不需要登录验证就可以进入后台的dashboard。就必须加上对admin的登录验证转发中间件了。但是这样一来会导致无限验证循环。具体解决方法可以参见“[https://learnku.com/articles/5489/larval-53-multi-authority-login-correct-position](Laravel 5.3 自带多权限登录正确姿势)
    ”。其实,回过头重新看看kernel中

    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
                ……
  • 我们会发现最简单的方法就在眼前,就是把RouteServiceProvider.php中添加的方法写成:

    protected function mapAdminRoutes()
    {
        Route::group([
            'namespace'  => 'App\Http\Controllers\Admin',
            'prefix'     => 'admin',
            'middleware' => 'web',
        ], function ($router) {
            require base_path('routes/admin.php');
        });
    }
  • 也就是直接通过web中间件进行一般的基础验证,这些验证机制不正好是我们刚才在处理登录过程中碰到的各种问题所需要用到的验证中间件吗,接着再在routes/admin.php中进行路由分组,在分组中添加对admin权限的认证。

本作品采用《CC 协议》,转载必须注明作者和本文链接
努力是不会骗人的!
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!