我们正在使用带有Memcached的外部Ubuntu服务器来进行会话存储。由于我们从数据库会话中进行了更改,因此我们收到了正在注销的用户的随机投诉。
问题:
今天,我们的一位用户偶然发现了一种重现行为的方法。在允许他们设置自定义日期范围的页面上,他们反复按下“前一天”按钮,每次点击发送一个POST请求。例如,如果您单击所述按钮20次,它将发送20个POST请求,其中19个将在最后一个成功完成之前被取消。一旦最终请求完成,似乎所有会话变量都会丢失。
我的php.ini(CGI)设置:
session.save_handler = memcache
session.save_path = "tcp://OURSERVERIP:11211?persistent=1&weight=1&timeout=1&retry_interval=15"
注意:POST请求正在同一个域中加载iframe。
更新:用户登录时似乎也遇到了问题。会话ID冲突?
答案 0 :(得分:2)
我已经对你发布的所有内容做了一些研究,这里有一些固定点:
根据This article,有37 ^ 31个不同的会话ID。根据{{3}},你需要2E24个会话才有50%的几率碰撞一对。你可以看到机会极低,但可能。例如,如果您在数据库中存储会话ID,然后将其交给用户,以便他们可以使用相同的会话ID一年甚至更长时间,则可能会有所增加。
此时我不确定“前一天”按钮是否发送ajax请求,以便用户可以连续多次单击它而无需等待结果,或者他需要等待(至少部分)页面加载才能单击新加载页面中的按钮。在第一种情况下,可能发生数据包可能在互联网中被扰乱并且已经作为最后发送的请求将比其他请求更快地到达。现在当两个请求一次到达时会发生什么? 根据birthday paradox SO问题,会话数据被锁定,直到(通常)脚本完成执行。这会导致多个请求堆积在队列中,因此它应该是安全的,并且不会导致会话丢失。
这是最后一个重点,根据您的信息,我相信这是您的会话损失的原因。这取决于您的服务器的实现方式,但如果第10个“前一天”请求在第5天之前到达会发生什么?第二个可能的原因是中断页面加载。 ajax加载不会发生这种情况,但它会以常规形式发生。如果您在加载页面之前单击前一天(并且可能仍在执行),则Web浏览器会中断加载并请求新页面。然后php脚本执行this。 现在根据aborted,每当脚本终止时都会调用该函数,因此在这种情况下它仍然是会话安全的。那么问题出在哪里?可能在剧本中再次出现。想象一下,你的php脚本将在中间停止执行并立即保存会话。会发生什么?这取决于。取决于你如何处理会话,你存储在什么,什么时候存储它。它基本上可以在任何添加(回显)输出的行中死掉,因为当它发现客户端浏览器不再监听连接时就是这样。
我相信这是原因,我可能错了,因为只有你能看到你的代码。我建议您查看代码并检查如果您的脚本提前终止或无序收到请求会发生什么。
修改强> 我忘记了memcache。不幸的是我对它一无所知所以标记了一些不正确的东西,但没有从这个答案中删除,那是因为休息仍然是正确的原因。
答案 1 :(得分:2)
根据你的写作,我可以区分两个不同的问题:
这些可能是不同的问题,或者相同,我无法分辨。更严重的问题是人们可以获得其他人的会话ID。这很奇怪。
如果我正确地解释了你的问题,你会问:“其他人在使用Memcached的Ubuntu服务器上的会话有类似的问题吗?”。
对不起,不,我没有那种经历。与您的源代码相关的问题无法回答,尽管它们可能是您问题的根源。特别是ID问题的变化。
你见过这个吗?
http://php.net/manual/en/memcached.sessions.php#115306
这听起来不像你的问题,但任何信息都可以提供帮助。
至于我的提示:
a:如果你想处理大量流量,你的服务器需要相当多的内存。检查服务器随着时间的推移有多少可用内存,它是否接近于零?这将导致较旧的会话从MemCache中清除并重置连接。
b:检查404 Not Found
个错误的所有内容。使用浏览器控制台检查每个页面加载。图像或CSS文件上的404可以重置会话,从而导致偶发会话丢失。
c:确保未重新生成会话ID。它可能会导致您描述的问题。 (https://bugs.php.net/bug.php?id=61470&edit=1)
d:尝试在您的问题中添加更多源代码。给人们一些看待和尝试的东西。如果长时间使用类似http://ideone.com的内容,我知道这不包括您的数据库或流量负载,但它可能会帮助我们找到您的问题。
如果您确实解决了问题,请告诉我们。