网站内容更新机制(怎么证明thinkPHP5框架对于session的操作是正确的的呢?)

优采云 发布时间: 2021-10-05 21:18

  网站内容更新机制(怎么证明thinkPHP5框架对于session的操作是正确的的呢?)

  背景

  最近接手维护了一个网站,后端api使用thinkPHP5的框架,版本号为5.0.22,网站的登录是cookie,session机制,session的存储介质是redis,设置为30min过期。

  偶尔有用户反馈说会话半小时前就过期了,自动跳转到登录界面,要求他重新登录。

  emmm,客户的表情,其实是用户从自己时间感知层面说出来的一种现象。

  但问题是,每个人在不同的心理状态下,对时间的感知是不同的。一个典型的例子是,人们进入一种流动状态后,感觉时间过得很快。

  那么,我们如何证明ThinkPHP5框架对于会话操作是正确的呢?正确性主要是针对,用户登录后,在操作界面几分钟后,会触发一些后端API,session的过期时间会重置为30min吗?!

  让我们开始我们的查询过程。

  探索

  我们如何做一个小实验来证明用户登录后,经过一段时间(小于30分钟),登录后需要访问的后端API被触发,以及会话是刷新还是重置为 30 分钟?

  下面我的实验截图是在线服务器的redis docker容器中做的一个实验:

  

  所以,此时我们可以初步判断thinkPHP5框架对于存储介质为redis的session的刷新操作是没有问题的。

  这时候用户就问,间隔操作的api是否会存在个体操作差异。比如我这里用于实验操作的api就是Task控制器下的getTaskList方法。那怎么证明用户登录后,触发任何post 结束api都会刷新session的过期时间!!!

  emmm,别告诉我,你真的别再问我了,吸氧,冷静一下!

  其实客户问的是框架底层刷新session过期时间的原理,或者说通俗一点就是框架源码的逻辑是如何刷新或者重置session时间的,避免session过期时间是硬编码的 30 分钟,而不是动态的 30 分钟羊毛布?

  那么,只能牺牲xdebug这个调试神器,用断点调试,同时手动监控(如上图,看框架生命周期源码执行后创建redis键?哪里?部分源代码刷新时间?)Redis key变化。

  下图展示了如何进入think\session的init配置并实例化session对象:

  

  最后一种将会话密钥写入redis的方法是:

  

  注意:

  1.Redis->write 方法是判断配置的session的过期时间是否大于0,如果大于0,则将数据写入redis。sexex 是指定redis向key写入数据的过期时间。这里的过期时间是默认的30min;

  2.session_write_close 是一个会自动调用的 php 方法。调用后会触发Redis->write方法,但是当你尝试ctrl+鼠标左键查找谁调用了write时,却找不到。原因是什么:

  

  中文翻译如下:

  结束当前会话的会话并将数据存储在会话中。(存储是指写入文件或redis)

  session数据通常是在php脚本执行之后存储的,而不是在代码层面调用session helper函数或者session对象的设置值,session值会立即存储在redis或者file中,这个时候只要会话值写入内存 $_SESSION 数组。

  脚本结束了将会话写入存储介质的操作,无需我们手动调用 session_write_close() 方法,但是由于会话数据被锁定以防止并发写入,因此任何会话在任何时候都只能由一个脚本进行操作。

  以When开头的长句,大概的意思是,因为脚本锁了session,所以我们的脚本应该尽可能快的执行,避免高并发,当不同的脚本操作同一个session时,因为锁存在,只有session锁可以排队,后面的脚本要等前面的脚本自动释放会话锁才可以操作会话。因此,提高脚本的执行速度,减少脚本的执行时间,会减少会话锁的持续时间。然后可以提高同一会话上不同脚本操作的并发性。

  所以session存储介质应该优先redis,而不是file。毕竟内存级写操作比磁盘写快几个数量级?!

  综上所述

  目前从后端源码来看,刷新session的过期时间或者重置过期时间都看不出问题。

  那么是不是客户端进入了一种流动的状态,让人感觉时间过得很快呢?让他觉得会话快到期了?可能需要配合前端查看会话级cookie是否无效?

  2021-05-07 11:40:51 探讨session cookie的问题

  上面我们已经确定了session会刷新更新,但是为什么客户在使用了反馈之后还是会跳转到登录页面呢?

  如果我直接告诉客户是心流的原因,我怕客户会被打死。既然他肯定会用,他就会被重定向到登录界面。至少前端cookie中存储的sessionid的cookie的过期时间应该是有例外的!

  session需要和cookie一起使用。session是存储在服务器上的状态信息,所以cookie中存储的sessionid是为了记录浏览器和session的映射关系;

  创建会话时,通过 API 请求的最终响应将这个 cookie 提供给客户端。cookie是可以设置时间的,所以很有可能每次触发API的时候session都会刷新session的过期时间!

  但是cookie过期时间没有刷新,是固定的30min,导致客户端浏览器级别检测到cookie已经过期,于是js将页面重定向到登录界面!

  那么,thinkphp5.0.22 在哪里设置cookie过期时间呢?看截图:

  

  

  ini_set() 函数的意思是在运行阶段动态修改配置文件的值!在thinkphp5.0.22的session初始化阶段,会给出cookie的过期时间作为session的过期时间,但是可以刷新session的过期时间,cookie不是!

  所以,只需将其更改为会话cookie(cookie_lifetime=0)即可解决问题!

  补充

  忘记回答问题了,“如何证明用户登录后会在触发任何后端API后刷新会话的过期时间?”

  本质上你提到了对session源代码的探索,那么session的读写一般发生在用户登录的时候。 比如我维护了网站 session来判断用户是否登录写在公共控件的基类中:

  

  

  

  

  

  参考文件:

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线