[英]Codeigniter 3 upgrade session lock causing issues
我们最近已将旧的Codeigniter应用程序从2.1.0升级到3.1.9,一切进展顺利。 除此之外,新的会话锁定会引起问题,我想知道修复它的正确方法。
该应用程序大量使用AJAX,但是大多数AJAX调用不会写入会话,并且似乎也不会中断会话。
这是一个问题的示例:存在一个带有复选框的GUI,并且当更改输入(选中或取消选中复选框)时,将进行AJAX调用。 在该AJAX呼叫的另一端,将选中了复选框的会话写入会话,以便每次访问时都能记住它们。 但是,如果您选中/取消选中多个框而导致多个AJAX呼叫中断,则最终将被注销。 在所有正在执行会话写操作的应用程序周围都发现了类似的行为。
我尝试按照Codeigniter文档的建议实施session_write_close()
,但是只有一半在某些地方有效,并且在以前没有问题的区域中引起了更多问题。 该应用程序具有几个可以完成所有工作且所有工作流都共享的端点,因此使用session_write_close()
修复会话写入发生的端点时,当它们继续需要会话时,会中断其他脚本调用。
我想出的短期解决方案是对AJAX调用进行反跳(这有助于但不能单独解决问题),并禁用输入,直到AJAX调用完成。
有更好的长期解决方案吗? 最终,该应用已被淘汰,因此花很长时间重写它是不可行的。
唯一的长期解决方案是正确使用session_write_close()
。
毫无疑问,会话数据已锁定,因此在任何时候只有一个脚本可以写入会话的持久性数据存储。 会话锁定可防止对并发错误进行故障排除,并且更加安全。
如果没有看到您的实现,这真的很难,呃……无法提供任何准确的建议。 这里有一些需要考虑的事情可能有助于弄清混乱。
无论是做所有或会话没有在AJAX响应函数写。 (通过“ AJAX响应功能”,我指的是AJAX网址的PHP controller/method
值。)
使用ALL方法,在发出任何AJAX请求之前,请在“主要”脚本中调用session_write_close()
。 请记住, $_SESSION
不受session_write_close()
影响。 主脚本中的所有$_SESSION
项都将保持可访问状态,因此您可以可靠地读取值。 但是,将不会写入对$_SESSION
所做的更改 ,因为就PHP而言,该会话已关闭。 但这仅适用于调用session_write_close()
的脚本。
使用NONE方法,您可能仍需要读取会话数据。 在那种情况下,最好让AJAX响应函数尽快调用session_write_close
,以最大程度地减少并发请求被阻塞的时间。 对于需要大量时间才能执行的功能,该调用更为重要。 如果脚本执行时间很短,则不需要显式调用session_write_close()
。 如果有可能,即无需读取会话数据,则不加载session
类可能会导致代码更简洁。 肯定会消除并发请求阻塞的任何机会。
不要尝试通过在同一浏览器上使用多个选项卡来测试同一应用程序来测试会话行为。
考虑使用$config['sess_time_to_update'] = 0;
然后显式调用$this->sess_regenerate((bool) config_item('sess_regenerate_destroy'));
需要更改会话ID的时间和地点,即登录后立即更改; 重定向到“敏感”页面后; 等等
接下来的内容带有大量的恐惧。 我已经使用“文件”驱动程序对此进行了测试,但是还没有进行广泛的测试。 因此,买家要当心。
我发现这是可能的“重新启动”会话通过调用PHP函数session_start()
之后session_write_close()
已被使用。 CodeIgniter将打开并读取会话数据存储,并重建$_SESSION
超全局变量。 现在可以更改会话数据,它将在脚本执行结束时写入-或通过另一个对session_write_close()
调用来写入。
这是有道理的,因为session_write_close()
不会对CodeIgniter session
对象执行任何操作。 该类仍被实例化和配置。 CodeIgniter的自定义SessionHandlerInterface
用于在调用session_start()
之后打开,读取和写入会话数据。
也许这种明显的功能可以用来解决您的问题。 如果我之前不清楚,请自担风险!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.