热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

关于扩展Laravel默认Session中间件导致的Session写入失效问题分析,laravelsession_PHP教程

关于扩展Laravel默认Session中间件导致的Session写入失效问题分析,laravelsession_PHP教程:关于扩展Laravel默认Session中间件导致的S

关于扩展 Laravel 默认 Session 中间件导致的 Session 写入失效问题分析,laravelsession


最近由于项目开发需要,手机客户端和网页端统一使用一套接口,为保证 会话(Session) 能够正常且在各类情况下兼容,我希望能够改变 SessionID 的获取方式。默认情况下,所有网站都是通过 HTTP 请求的 Header 头部中的 COOKIE 实现的,通过 COOKIE 中指定的 SessionID 来关联到服务端对应数据,从而实现会话功能。

但对于手机客户端,可能并不会支持原始的 COOKIE,亦或者根据平台需要而屏蔽,因此开发中要求通过增加一个请求头 X-Session-Token 来标识 SessionID。在 Laravel 框架中,实现 Session 初始化、读取和启动,都是通过 Illuminate\Session\Middleware\StartSession 这个中间件实现的,该中间件有一个关键方法 getSession ,这个方法就是获取 SessionId 从而告知 Session 组件以什么凭据恢复 Session 数据。

该中间件注册于 app/Http/Kernel.php 文件下。

我新建了一个类继承该中间件,同时替换了在 app/Http/Kernel.php 下的注册的地方,原来的 getSession 方法源码如下:

public function getSession(Request $request) { $session = $this->manager->driver(); $session->setId($request->COOKIEs->get($session->getName())); return $session; }

在新的中间件中,我修改为:

public function getSession(Request $request) { $session = $this->manager->driver(); // 判断是否是接口访问并根据实际情况选择 SessionID 的获取方式 if ($request->headers->has('x-session-token')) { $sessiOnId= $request->headers->has('x-session-token'); } else { $sessiOnId= $request->COOKIEs->get($session->getName()); } $session->setId($sessionId); return $session; }

但是麻烦也随之而来。。。

修改完后,推送至分支,在合并至主开发分支之前往往需要跑一下单元测试,不幸的是,之前通过的 Case 这回竟然报错,问题是 CSRF 组件 报出 Token 错误,而我们在这一处提供的 Token 跟平时并无二致,问题肯定出在 Session 上。

值得注意的是,我修改中间件的代码,对框架的影响可以说根本没有,事实上也确实没有,因为我将我自己创建的中间件代码修改成继承的中间件代码一致也无济于事,但奇怪的是,在我将中间件换回原来的中间件就没有这个问题。

于是我将正常情况下和非正常情况下的代码都跑了一遍,在关键处断点调试,发现问题出在中间件的一个重要属性 $sessionHandled , 若该值为 false 则会引起我们之前的状况。关键在于,中间件启动之时,都会走 handle 方法,而对于 Session 这个中间件, handle 方法的第一行代码就是:

$this->sessiOnHandled= true;

Interesting。。。

我们知道。Laravel 框架的特色是其 IoC 容器,框架中初始化各种类都是由其负责以实现各种依赖注入,以保证组件间的松耦合。中间件定然不例外。要知道,单例和普通实例最大的区别在于无论创建多少次,单例永远都是一个,实例中的属性不会被初始化,因此无问题的中间件必然是一个单例,而我自己创建的中间件只是个普通的类的实例。但本着知其然更要知其所以然,我需要确认我这一想法(其实解决办法已经想到了,后面说)。

那么问题大致就在于初始化中间件这块了,于是不得不打起精神,仔细理一下 Laravel 的启动代码。而这里面的重点,在于一个叫 Illuminate\Pipeline\Pipeline 的类。

这个类有三个重要方法 send 、 through 、 then 。其中 then 是开始一切的钥匙。这个类主要是连续执行几个框架启动步骤的玩意儿,首先是初始化处理过程需要的组件(Request 和 中间件),其次是将请求通过这些处理组件构成的堆栈(一堆中间件和路由派发组件),最后是返回处理结果(Response)。

可以说这玩意儿是 Laravel Http 部分的核心(额,,本来就是 Kernel)。那么之前的问题就在于 Pipeline 的 then 方法和其调用的 getSlice 方法,直接观察 getSlice 方法,可以发现它负责的是生成处理堆栈,并实例化 Middleware (中间件)类,整个方法代码如下:

protected function getSlice() { return function ($stack, $pipe) { return function ($passable) use ($stack, $pipe) { if ($pipe instanceof Closure) { return call_user_func($pipe, $passable, $stack); } else { list($name, $parameters) = $this->parsePipeString($pipe); return call_user_func_array([$this->container->make($name), $this->method], array_merge([$passable, $stack], $parameters)); } }; }; }

可以注意到 $this->container->make($name) ,这意味着其初始化一个中间件类,单纯的就是 make,若其不是单例则反复 new ,导致之前的属性被初始化。

那么解决办法也显而易见面,使其成为一个单例。

我在 app/Providers/AppServiceProvider.php 的 register 方法中添加如下一行代码,就解决了之前的问题:

$this->app->singleton(SessionStart::class); // SessionStart 是我那个中间件类名

以上给大家介绍了扩展 Laravel 默认 Session 中间件导致的 Session 写入失效问题分析的全部内容,希望大家喜欢。

您可能感兴趣的文章:

  • Session对象失效的客户端解决方法
  • 异步 HttpContext.Current实现取值的方法(解决异步Application,Session,Cache...等失效的问题)
  • 浏览器关闭使session失效的问题多种解决方式
  • iframe跨域与session失效问题的解决办法
  • Laravel 5框架学习之Eloquent (laravel 的ORM)
  • Laravel 5框架学习之表单
  • Laravel 5框架学习之日期,Mutator 和 Scope
  • Laravel 5框架学习之表单验证
  • Laravel 5框架学习之Eloquent 关系
  • Laravel 5框架学习之用户认证
  • Laravel 5 框架入门(一)

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/1089945.htmlTechArticle关于扩展 Laravel 默认 Session 中间件导致的 Session 写入失效问题分析,laravelsession 最近由于项目开发需要,手机客户端和网页端统一使用一套...


推荐阅读
  • HTML:  将文件拖拽到此区域 ... [详细]
  • 本文详细介绍了PHP中的几种超全局变量,包括$GLOBAL、$_SERVER、$_POST、$_GET等,并探讨了AJAX的工作原理及其优缺点。通过具体示例,帮助读者更好地理解和应用这些技术。 ... [详细]
  • Fiddler 安装与配置指南
    本文详细介绍了Fiddler的安装步骤及配置方法,旨在帮助用户顺利抓取用户Token。文章还涵盖了一些常见问题的解决方案,以确保安装过程顺利。 ... [详细]
  • 在尝试加载支持推送通知的iOS应用程序的Ad Hoc构建时,遇到了‘no valid aps-environment entitlement found for application’的错误提示。本文将探讨此错误的原因及多种可能的解决方案。 ... [详细]
  • 本文详细探讨了在Web开发中常见的UTF-8编码问题及其解决方案,包括HTML页面、PHP脚本、MySQL数据库以及JavaScript和Flash应用中的乱码问题。 ... [详细]
  • 在现代Web开发中,HTML5 Canvas常用于图像处理和绘图任务。本文将详细介绍如何将Canvas中的图像导出并上传至服务器,适用于拼图、图片编辑等场景。 ... [详细]
  • 本文详细介绍了如何处理Oracle数据库中的ORA-00227错误,即控制文件中检测到损坏块的问题,并提供了具体的解决方案。 ... [详细]
  • Kubernetes Services详解
    本文深入探讨了Kubernetes中的服务(Services)概念,解释了如何通过Services实现Pods之间的稳定通信,以及如何管理没有选择器的服务。 ... [详细]
  • 本文详细介绍了在PHP中如何获取和处理HTTP头部信息,包括通过cURL获取请求头信息、使用header函数发送响应头以及获取客户端HTTP头部的方法。同时,还探讨了PHP中$_SERVER变量的使用,以获取客户端和服务器的相关信息。 ... [详细]
  • Hibernate全自动全映射ORM框架,旨在消除sql,是一个持久层的ORM框架1)、基础概念DAO(DataAccessorOb ... [详细]
  • Maven + Spring + MyBatis + MySQL 环境搭建与实例解析
    本文详细介绍如何使用MySQL数据库进行环境搭建,包括创建数据库表并插入示例数据。随后,逐步指导如何配置Maven项目,整合Spring框架与MyBatis,实现高效的数据访问。 ... [详细]
  • 编译原理中的语法分析方法探讨
    本文探讨了在编译原理课程中遇到的复杂文法问题,特别是当使用SLR(1)文法时遇到的多重规约与移进冲突。文章讨论了可能的解决策略,包括递归下降解析、运算符优先级解析等,并提供了相关示例。 ... [详细]
  • Python Requests模块中的身份验证机制
    随着Web服务的发展,身份验证成为了确保数据安全的重要环节。本文将详细介绍如何利用Python的Requests库实现不同类型的HTTP身份验证,包括基本身份验证、摘要式身份验证以及OAuth 1认证等。 ... [详细]
  • 如何处理PHP缺少扩展的问题
    本文将详细介绍如何解决PHP环境中缺少扩展的问题,包括检查当前环境、修改配置文件以及验证修改是否生效的具体步骤,帮助开发者更好地管理和使用PHP扩展。 ... [详细]
  • Android异步处理一:使用Thread+Handler实现非UI线程更新UI界面Android异步处理二:使用AsyncTask异步更新UI界面Android异步处理三:Handler+Loope ... [详细]
author-avatar
0Hey0ne
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有