关于扩展 Laravel 默认 Session 中间件导致的 Sessio
Laravel 默认 Session 中间件扩展与 Session 写入失效的挑战
在项目开发中,为了满足手机客户端和网页端统一接口的需求,我们期望改变 SessionID 的获取方式。通常,网站通过 HTTP 请求的 Header 头部中的 Cookie 来获取 SessionID,以此关联服务端数据,实现会话功能。但对于手机客户端,由于平台限制可能并不支持或屏蔽了原始的 Cookie 方式。为此,我们决定通过增加一个请求头 X-Session-Token 来标识 SessionID。
在 Laravel 框架中,Session 的初始化、读取和启动是通过 Illuminate\Session\Middleware\StartSession 这个中间件来实现的。该中间件有一个关键方法 getSession,它是获取 SessionId 并告知 Session 组件以什么凭据恢复 Session 数据的关键。这个中间件在 app/Http/Kernel.php 文件中被注册。
为了适配新的 SessionID 获取方式,我创建了一个新类继承自该中间件,并替换了原有的注册方式。在修改 getSession 方法时,我增加了一个判断逻辑来根据请求头选择 SessionID 的获取方式。在测试过程中遇到了问题。
在修改完成后,我进行了单元测试,但令人困惑的是,之前通过的测试用例竟然报错了。错误来自于 CSRF 组件的 Token 错误。提供的 Token 与平时无异,问题肯定出在 Session 上。值得注意的是,我对中间件的修改对框架的影响理论上是非常小的。事实上也确实如此,即使我将自己创建的中间件代码修改得与继承的中间件代码一致,问题依然存在。但奇怪的是,当我将中间件换回原来的中间件时,问题就消失了。
于是我对正常情况下和非正常情况下的代码都进行了仔细分析,并在关键处设置断点进行调试。最终发现问题出在中间件的一个重要属性 $sessionHandled 上。若该值为 false,则会导致之前遇到的状况。关键在于,中间件启动时都会执行 handle 方法,而对于 Session 中间件来说,handle 方法的第一行代码就是设置 $sessionHandled 为 true。这是一个有趣的发现。
我们知道 Laravel 框架的特色是其 IoC 容器,它负责初始化各种类并实现依赖注入,以保证组件间的松耦合。中间件也不例外。我们意识到问题的关键可能在于中间件的初始化过程。由于单例和普通实例在 Laravel 中的处理方式不同,单例的属性不会被初始化多次。我推测有问题的中间件可能不是一个单例,而我自己创建的中间件只是一个普通的类的实例。但这只是我的猜测,为了真正解决问题并深入了解其背后的原因,我决定深入研究 Laravel 的启动代码。深入理解 Laravel 中的 Illuminate\Pipeline\Pipeline 类
在 Laravel 框架中,有一个非常重要的类叫做 Illuminate\Pipeline\Pipeline,它是整个框架中处理请求和响应的核心组件之一。这个类拥有三个重要的方法:send、through 和 then。其中,then 方法是启动一切的钥匙,它负责连续执行几个框架启动步骤,初始化处理过程所需的组件(包括 Request 和 中间件),并通过这些处理组件构成的堆栈来处理请求,最终返回处理结果(Response)。
在 Laravel 的 Http 部分,Pipeline 堪称核心,特别是在处理中间件时。而其中的重点则在于 Pipeline 的 then 方法和其调用的 getSlice 方法。通过观察 getSlice 方法的代码,我们可以发现它主要负责生成处理堆栈并实例化 Middleware(中间件)类。
在这个方法中,如果 $pipe 是一个闭包,那么就直接调用它。否则,它会管道字符串,调用容器中相应的中间件类的方法。这里有一个问题需要注意,那就是在初始化中间件类时,如果它不是单例,那么每次都会新建一个实例,这可能会导致之前的属性被重新初始化。
为了解决这个问题,我们可以将中间件类设置为单例。我们可以在 app/Providers/AppServiceProvider.php 文件的 register 方法中添加一行代码来实现这个目标。例如,如果你的中间件类是 SessionStart,那么你可以添加这样一行代码:$this->app->singleton(SessionStart::class); 这样就能确保 SessionStart 类在整个应用生命周期中只有一个实例。
Laravel 中的 Illuminate\Pipeline\Pipeline 类在处理请求和响应时扮演着重要的角色。通过深入理解其工作原理,特别是 then 方法和 getSlice 方法的运行机制,我们可以更好地解决在使用 Laravel 框架时遇到的问题,比如扩展默认 Session 中间件导致的 Session 写入失效问题。
以上就是对 Laravel 中 Illuminate\Pipeline\Pipeline 类的介绍,以及其在实际应用中的使用和分析。希望大家能更好地理解这个类的功能和作用,并在实际开发中更加得心应手。也欢迎大家提出宝贵的建议和反馈,共同学习和进步。Cambrian.render('body') 的部分似乎与文章主题无关,已被过滤掉。
编程语言
- 关于扩展 Laravel 默认 Session 中间件导致的 Sessio
- 用react-redux实现react组件之间数据共享的方法
- sql语句优化之SQL Server(详细整理)
- AspNetPager分页控件 存储过程
- jQuery.form插件的使用及跨域异步上传文件
- PHP实现 APP端微信支付功能
- PHP实现的日历功能示例
- Jquery+Ajax+PHP+MySQL实现分类列表管理(下)
- DATASET 与 DATAREADER对象有什么区别
- PHP substr()函数参数解释及用法讲解
- JS+CSS实现滑动切换tab菜单效果
- 如何用webpack4从零开始构建react开发环境
- Vue微信授权登录前后端分离较为优雅的解决
- Fatal error- Allowed memory size of 134217728 bytes exhauste
- laravel框架关于搜索功能的实现
- react实现antd线上主题动态切换功能