如何在某些场景下关闭 Laravel 的自动 Session 会话生成

说明

在以下的这些特殊场景下,我们需要关闭 Laravel Session 的生成:

  • 测试环境下;
  • 特殊逻辑下,如你想未登录用户不创建会话信息,如这里讨论的 问答:session 问题

在 5.3 里有非常棒的 中间件组 功能可以来处理此类问题,接下来介绍适用于 5.1 的方法。

测试环境下

在运行测试时,Laravel 会自动将环境变量设置为 testing,并将 Session 及缓存以 数组 的形式存入,也就是说在测试时不会保存任何的 Session 或缓存数据。

来自:https://learnku.com/docs/laravel/5.1/testing#测试环境

也就是说我们什么都不需要做。

未登录用户情况下关闭 Session

原理:从上面测试环境的讲解中,我们知道了将 Session 驱动设置为 数组 的形式存入,就不会保存任何的 Session 数据。

利用这个原理,我们在可以新增一个全局中间件,在此中间件中将 Session 驱动设置为 数组,并且此中间件运行在 StartSession 中间件之前即可。

一、注册全局中间件

注意要放在 StartSession 之前:

    protected $middleware = [
    ...
        \App\Http\Middleware\DisableSessionMiddleware::class,
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\VerifyCsrfToken::class,
    ];

二、书写代码

DisableSessionMiddleware 类的代码如下:

<?php

namespace App\Http\Middleware;

use Closure;

class DisableSessionMiddleware
{
    public function handle($request, Closure $next)
    {
        // 如果是未登录用户的话,关闭 Session 记录
        if (!Auth::check() && !$request->is('auth/*') ) {
            config()->set('session.driver', 'array');
        }
        return $next($request);
    }
}

三、关闭 CSRF 认证

修改 VerifyCsrfToken 类:

<?php

namespace App\Http\Middleware;

use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;

class VerifyCsrfToken extends BaseVerifier
{
    /**
     * The URIs that should be excluded from CSRF verification.
     *
     * @var array
     */
    protected $except = [
        //
    ];

    public function handle($request, Closure $next)
    {
        // 如果是未登录用户的话,关闭 CSRF 认证
        if (!Auth::check()) {
            return $next($request);
        }
        return parent::handle($request, $next);
    }
}
摈弃世俗浮躁,追求技术精湛
Summer
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 11

数组驱动,这个巧妙

7年前 评论
Destiny

:punch: 哈, 干活十足呀.....Test Name

7年前 评论

测试了这种方法,会导致TokenMismatchException,如果去掉VerifyCsrfToken中间件,又会导致分明已经登录了系统,session()->put了数据,但是下次sesssion()->get又为空;个人分析原因可能是两次访问的sessionid并不同

7年前 评论
Summer

@peterlee 已更新,再试试

7年前 评论

@Summer 再次测试,TokenMismatchException解决了,但是Auth::check()始终为false,导致用户无法登陆系统

7年前 评论
Summer

@peterlee 因为未登录的用户都设置了 array,所以即使是尝试登陆的用户都会使用 array 去做 session 驱动,所以用户无法登录。

7年前 评论
Summer

@peterlee 加一个 url 判断应该就可以了:

if (!Auth::check() && !$request->is('auth/*') ) {
            config()->set('session.driver', 'array');
        }
7年前 评论

@Summer 加了之后,点击任何链接都无反应

7年前 评论

@Summer 打印log发现,登录后session已经保存到file里面了,但是get的时候,始终为空

7年前 评论
Summer

@peterlee 现在在着急处理点东西,回头我再整整,或者你能解决了 @ 我下答案 :smile_cat:

7年前 评论

我也出现了Auth::check()始终为false,导致用户无法登陆系统,求指导,紧急。。。

5年前 评论

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