多次(已取消)POST请求后,会话丢失。

3
我们正在使用一个外部的Ubuntu服务器和Memcached来存储我们的会话。自从我们从数据库会话切换过来后,我们收到了一些用户的随机投诉,他们被注销了。
问题如下:
1.用户在他们的会话到期之前被注销。在某些情况下,他们在登录后的一两分钟内就被注销了。 2.我们的Web服务器日志或Memcached日志中没有出现任何错误。 3.他们的会话ID在被注销后仍然保持不变。
今天,我们的一个用户偶然发现了一个复现该行为的方法。在一个允许他们设置自定义日期范围的页面上,他们反复按“前一天”按钮,每次点击都会发送一个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冲突?

@derp 不幸的是,日志并没有提供太多帮助,这就是让人感到沮丧的原因。我马上会添加我的Memcached php.ini设置。 - Wayne Whitty
也许你已经知道了,但我还是想提一下在开始之前给一个 session_name('myproject') - Santa's helper
你是否正在使用 session_regenerate_id() - Jasper N. Brouwer
@JasperN.Brouwer 我前天才开始处理这个问题。同时引入了基于用户代理的会话令牌,以避免冲突。 - Wayne Whitty
我们在使用floatbox 2.45时遇到了类似的问题,其中一对图像在服务器上丢失。我们发现其中4个图像出现了404错误。只有在IE11和Edge中,我们才能不时地复制该问题。一旦我们添加了这些图像,问题就解决了 ;) - jszoja
2个回答

2

我已经对你发布的所有内容进行了一些研究,以下是一些要点:

会话ID冲突

根据这篇文章,有37^31个不同的会话ID。根据生日悖论,您需要2E24个会话才能有50%的机会出现碰撞。可以看出机会非常低,但仍然可能发生。如果您将会话ID存储在数据库中并稍后交给用户,使他们可以在一年甚至更长时间内使用相同的会话ID,则机会略微增加。

多个同时会话请求

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

脚本时间特定的弱点

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

我认为这可能是原因,但我可能是错的,因为只有你能看到你的代码。我建议您检查代码并查看如果脚本过早终止或接收到错误请求会发生什么。
编辑:我忘记考虑memcache了。不幸的是我对它一无所知,所以一些不正确的东西被标记但没有从答案中删除,因为其余部分仍然可能是正确的原因。

2
从你写的内容中,我可以区分出两个不同的问题:
  1. 用户退出登录,但他们的会话ID没有改变。
  2. 用户的会话ID发生了改变。
这可能是不同的问题,也可能是相同的问题,我无法确定。更严重的问题是人们可以获得其他人的会话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的工具。我知道这不包括您的数据库或流量负载,但它可能有助于我们找到您的问题。

如果您解决了问题,请告诉我们。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接