php - 多个(取消的)POST 请求后 session 丢失

标签 php session memcached

我们使用带有 Memcached 的外部 Ubuntu 服务器来存储我们的 session 。自从我们从数据库 session 切换过来后,我们就收到了被注销的用户的随机投诉。

问题:

  1. 用户在 session 到期前被注销。在某些情况下,他们会在登录一两分钟后退出。
  2. 我们的网络服务器日志或 Memcached 日志中没有出现任何错误。
  3. 注销后他们的 session ID 保持不变。

今天,我们的一位用户偶然发现了一种重现该行为的方法。在允许他们设置自定义日期范围的页面上,他们反复按下“前一天”按钮,每次点击都会发送 POST 请求。例如,如果您单击该按钮 20 次,它将发送 20 个 POST 请求,其中 19 个将在最后一个成功完成之前被取消。一旦最终请求完成,似乎所有 session 变量都丢失了。

我的 php.ini (CGI) 设置:

session.save_handler = memcache
session.save_path = "tcp://OURSERVERIP:11211?persistent=1&weight=1&timeout=1&retry_interval=15"

注意:POST 请求正在同一域上加载 iframe。

更新:似乎也遇到了用户以彼此身份登录的问题。 session ID 冲突?

最佳答案

我对您发布的所有内容做了一些研究,这里有一些固定点:

session ID 冲突

根据 This article有 37^31 个不同的 session ID。根据birthday paradox您需要 2E24 个 session 才能有 50% 的机会出现一对碰撞。你可以看到机会极低,但有可能。例如,如果您将 session ID 存储在数据库中,然后将其交给用户,这样他们就可以使用相同的 session ID 一年甚至更长时间,这样的机会会稍微增加。

多个同时 session 请求

此时我不确定“前一天”按钮是否发送 ajax 请求以便用户可以连续多次单击它而无需等待结果,或者他需要等待(至少部分)页面加载才能单击在新加载的页面中再次单击该按钮。在第一种情况下,数据包可能会在 Internet 中被扰乱,最后发送的请求将比其他请求更快到达。现在当两个请求同时到达时会发生什么? <罢工>根据this所以质疑 session 数据被锁定,直到(通常)脚本完成执行。这会导致多个请求堆积在一个队列中,因此它应该是安全的并且不会导致丢失 session 。

脚本时间特定的弱点

这是最后一个要点,根据您的信息,我相信这是您 session 丢失的原因。这取决于您的服务器是如何实现的,但是如果第 10 个“前一天”请求在第 5 个之前到达会怎样?第二个可能的原因是中断页面加载。 ajax 加载不会发生这种情况,但它会以常规形式发生。如果您在页面加载前一天单击(并且可能仍在执行),您的网络浏览器会中断加载并请求新页面。然后 php 脚本执行应为 aborted . 现在我根据session_write_close每当脚本终止时都会调用该函数,因此在这种情况下它仍然是 session 安全的。 那么问题出在哪里呢?可能再次出现在剧本中。想象一下,你的 php 脚本将在中间停止执行并立即保存 session 。会发生什么?这取决于。取决于你如何处理 session ,你在里面存储什么,你什么时候存储它。它基本上可以在添加(回显)输出的任何行停止,因为那时它发现客户端浏览器不再监听连接。

我相信这是原因,我可能是错的,因为只有你能看到你的代码。我建议您检查代码并检查如果您的脚本提前终止或乱序接收请求会发生什么情况。

编辑 我忘了考虑内存缓存。不幸的是我对此一无所知所以一些不正确的东西被标记但没有从这个答案中删除,那是因为休息仍然可能是正确的原因。

关于php - 多个(取消的)POST 请求后 session 丢失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25806781/

相关文章:

html - 使用 LocalStorage 在移动 Web 应用程序中存储 Cookie 时出现问题

php - 刷新时 Codeigniter session 重置

PHP 垃圾收集器不断删除我的 session

python - 在内存缓存中获取/放入数据时指定超时(django)

redis - "Warning: Memcached::setOption() expects parameter 1 to be integer, string given"使用来自 "Redis Enterprise Cloud"的 Redis Memcached 和 Symfony 5

php - 使用 mysql 建立 php 错误数据库的最佳方法?

php - 将数字四舍五入到最近的间隔

php - 如何从 PHP 获取 Oracle SQL 查询的 EXPLAIN PLAN?

php - 4 :00pm on Saturday 之后的星期一禁用

python - memcache 不会存储键/值,因为值太大