【发布时间】:2026-01-13 23:45:01
【问题描述】:
当 2 个用户(几乎)同时访问同一页面时,我遇到了争用情况。这会导致用户获得对其他用户数据的访问权限。
几个月来,我一直在努力解决这个问题,终于成功了。 我使用的是Yii Framework 1.1,用户登录流程如下:
- 会话存储在数据库中,我实际上并没有使用 $_SESSION 来存储任何东西。
- 生成的会话 ID 存储在 cookie 中并填充 $_COOKIE,PHP 使用该 ID 将用户连接到他们的数据。
- 在登录页面中,我将 cookie 中的会话 ID 存储在表单的一个字段中。
- 用户登录,输入被验证,会话数据被创建并与用户记录一起存储,包括来自表单的会话ID(真实的会话ID)。然后,用户将通过另外 2 个控制器(LoginCheck、Dashboard)进入 Dashboard。
- 在会话期间,用户会频繁返回仪表板。
- 当 2 个或更多用户(几乎)同时访问仪表板页面(通过登录或从站点内的页面返回)时,两个用户最终将获得相同的 cookie id 和会话数据。我可以通过使用存储在 $_COOKIE 变量中的 cookie 值检查基于浏览器的 cookie 来确认这一点。使用不正确的数据在页面上简单刷新仪表板会导致加载正确的数据。
我研究了 PHP 会话的竞争条件,其中一些提供使用 $_COOKIE 来解决会话的竞争条件,因此并没有真正为我的问题提供任何解决方案。
由于我能够捕获问题,我可以通过刷新轻松解决它,但如果有更稳定的解决方案可用,我更愿意走这条路。
任何建议将不胜感激。
干杯
【问题讨论】:
-
听起来您的会话 ID 生成是基于时间戳的。例如,如果您使用的是
uniqid,那么这很容易导致您的问题。您应该研究使用加密安全值生成 ID 的替代方法,例如通过random_int或random_bytes。 -
除此之外,如果不查看任何实际代码,我们将无法真正为您提供帮助。这个问题可能是由许多事情引起的。我们需要查看代码才能缩小范围。
-
您的会话管理确实有问题。
session_id()php.net/manual/en/function.session-id.php 在每个会话中始终是唯一的。来自不同浏览器的用户无法获得相同的会话 ID。直到您人为地将其替换为损坏的实现。它与竞态条件无关 -
提供代码的问题大部分来自 Yii 框架,所以我一直假设/相信它会按预期工作。很难追踪这种情况发生的方式和时间,但我现在已经做到了。
-
@GregJ 我们不一定需要您的框架样板代码,但知道您使用哪个类来存储会话数据和/或生成会话 ID 和任何特定于应用程序的会话-相关的代码可以看看。
标签: php yii session-cookies yii1.x