Codeigniter 3 升级会话锁定导致问题

问题描述 投票:0回答:2

我们最近将旧的 Codeigniter 应用程序从 2.1.0 升级到了 3.1.9,一切都很顺利。除此之外,新的会话锁定导致了问题,我想知道修复它的正确方法。

该应用程序大量使用 AJAX,但是大多数 AJAX 调用不会写入会话,并且似乎不会破坏它。

以下是问题的示例:有一个带有复选框的 GUI,当输入更改(选中或取消选中复选框)时,会进行 AJAX 调用。在该 AJAX 调用的另一端,选中的框被写入会话中,以便每次访问时都会记住它们。但是,如果您选中/取消选中多个框,导致多个 AJAX 调用退出,您最终会被注销。在应用程序周围也发现了类似的行为,所有会话写入都发生。

我已经尝试按照

Codeigniter 文档
的建议实现 session_write_close(),但在某些地方只有一半有效,并且在以前没有问题的区域引起了更多问题。该应用程序有一些端点可以完成所有工作并且所有工作流程共享,因此使用
session_write_close()
修复会话写入发生的端点会在其他脚本调用继续需要会话时中断它们。

我提出的短期解决方案是消除 AJAX 调用(这有帮助,但本身并不能解决问题)并禁用输入,直到 AJAX 调用完成。

有更好的长期解决方案吗?最终这个应用程序将被淘汰,所以花很长时间重写它是不可行的。

php ajax codeigniter session
2个回答
3
投票

唯一的长期解决方案是正确使用

session_write_close()

您无疑明白,会话数据是锁定的,因此任何时候只有一个脚本可以写入会话的持久数据存储。会话锁定可以防止难以排除的并发错误,并且更安全。

如果没有看到你的实现,真的很难,呃……不可能提供任何精确的建议。以下是一些需要考虑的事项,可能有助于解决这个混乱的问题。

会话的 ALLNONE 都写入 AJAX 响应函数中。 (“AJAX 响应函数”是指 AJAX url 的 PHP

controller/method
值。)

使用 ALL 方法在发出任何 AJAX 请求之前在“主”脚本中调用

session_write_close()
。请记住,
$_SESSION
不受
session_write_close()
的影响。
main
脚本中的所有 $_SESSION 项目将保持可访问状态,以便您可以可靠地读取值。然而,对 $_SESSION 所做的
changes
不会被写入,因为就 PHP 而言,会话已关闭。但这仅适用于调用
session_write_close()
的脚本。

使用“NONE”方法,您可能仍然需要读取会话数据。在这种情况下,明智的做法是让 AJAX 响应函数尽快调用 session_write_close,以最大程度地减少并发请求被阻塞的时间。对于需要大量执行时间的函数来说,调用更为重要。如果脚本执行时间很短,则不需要显式调用

session_write_close()
。如果可能的话,即不需要读取会话数据,那么不加载
session
类可能会导致更干净的代码。这肯定会消除任何并发请求阻塞的机会。

不要尝试通过在同一浏览器上使用同一应用程序的多个选项卡来测试会话行为。

考虑使用

$config['sess_time_to_update'] = 0;

,然后在需要更改会话 ID 的时间和地点(即登录后)显式调用

$this->sess_regenerate((bool) config_item('sess_regenerate_destroy'));
;重定向到“敏感”页面后立即;等等

接下来的内容充满了极大的恐惧。我已经使用“文件”驱动程序对此进行了测试,但没有进行广泛的测试。所以,买家要小心。

我发现在使用

session_start()

后可以通过调用 PHP 函数

session_write_close()
来“重新启动”会话。 CodeIgniter 将打开并读取会话数据存储并重建
$_SESSION
超全局。现在可以更改会话数据,并且将在脚本执行结束时写入 - 或者再次调用
session_write_close()

这是有道理的,因为

session_write_close()

不会对 CodeIgniter

session
对象“做”任何事情。该类仍然被实例化和配置。 CodeIgniter 的自定义
SessionHandlerInterface
用于在调用
session_start()
后打开、读取和写入会话数据。

也许这个明显的功能可以用来解决您的问题。如果我之前不清楚 - 使用风险自负!


0
投票

© www.soinside.com 2019 - 2024. All rights reserved.