【问题标题】:Sessions are getting crossed. Ruby on Rails会话越来越多。 Ruby on Rails
【发布时间】:2013-02-06 19:34:15
【问题描述】:

我有一个应用程序正在使用设计进行身份验证。 ruby 1.9.2 上的 Rails 3,乘客位于 nginx 之上。

这是我的问题:我注意到我的会话有时会被越过。在以一个用户身份登录时,我有时会成为另一个用户。这真是一个可怕的问题。我已经设法通过使用 active_record 会话存储来停止它。但我对它可能发生的地方感到困惑。在使用 cookie 存储和 memcached 存储时都会发生这种情况。我不确定从哪里开始调试。我已经浏览了我所有的代码,我只是从“current_user”中读取而不是写入。我没有任何代码在会话中存储项目。

谁能给我建议,告诉我在哪里,或如何发生这种情况?

更新:

我在页面顶部设置了一个 div 来转储每个请求的会话内容。这不仅仅是用户切换,而是整个会话。我在会话中设置了一些虚拟变量,只是为了看看会发生什么。当会话越过时,(用户 A 变为用户 B)用户 A 现在看到用户 B 拥有的虚拟变量。用户 B 已注销。

更新 2

我在这里发现了另一个关于堆栈溢出的问题,它描述了同样的问题:In Rails, what could cause a user to have another user's session?

看起来可能是乘客问题?但更重要的是,它怎么会发生?这是一个真正的大问题。我该如何制止这种情况?

更新 3

我现在使用 Unicorn 来提供我的应用程序。我设置了 config.threadsafe!并开始专门使用活动记录会话。不再有 memcached 会话。问题消失了。至少我可以停止拔头发,因为安全孔被堵住了。

我仍然想知道究竟是什么原因造成的。那里的大多数教程都展示了如何使用默认的生成方法来设置乘客。自然,我认为 memcached 在会话管理方面的性能优于其他方法。尤其是在多应用服务器环境中。

更新 4

好的,最后一次更新。这是使用相同 memcached 连接的分叉进程的问题。我通过使用 dalli memcached 客户端修复它,并在独角兽或乘客的 after_fork 回调中重置连接。

【问题讨论】:

  • 您是否在同一个浏览器中使用不同的用户?还是您最近没有使用的完全随机的其他用户?
  • 未在同一浏览器中以不同的用户登录。即使在不同的网络上也会发生这种情况。用户 A 可能成为用户 B。即使他们位于不同的位置。它是随机发生的,我发现的唯一一件事是他们都必须登录才能发生。
  • 这可能是乘客问题吗? devise/warden 是否缓存 current_user 变量?
  • 我会到处添加调试...也许有些代码不是线程安全的?

标签: ruby ruby-on-rails-3 session devise


【解决方案1】:

我敢打赌你正在使用乘客的(默认)智能生成,并成为Spawning Gotcha 的受害者。

将您的PassengerSpawnMethod 设置为“conservative”,看看这是否会消失。这很容易解释 memcache 的情况,除非您正在防范它。大概是设计(或您的代码)中的类似问题。

您是否看到会话跨物理服务器,还是仅在一台服务器上?

【讨论】:

  • 目前我在一台机器上使用默认生成方法运行乘客。当前会话变量不能在请求之间正确清除。我无法想象,使用默认设置,其他人没有注意到这是一个问题。我会尝试保守的 spawn 方法,但是这种方法会破坏使用乘客的一些好处。
  • 如果它真的是会话变量,它也会影响activerecord会话,对吧?所以我认为不是这样。像这样的 Memcache 问题在乘客文档中明确指出(在那个陷阱中),所以你应该确保你已经涵盖了,如果没有,修复并返回到 memcache 会话。你能在开发环境中重现吗?
  • 此问题已通过使用 activerecord 会话暂时解决。最近我尝试使用 Unicorn 为应用程序提供服务,Unicorn 似乎也在发生这种情况。
【解决方案2】:

这个错误很可能可以通过升级到 rack-cache 1.2 或更高版本来修复。这是可能发生的事情:

  1. 用户 A 请求页面。创建一个会话并在响应中返回一个 Set-Cookie 标头。
  2. Rack-cache 错误地缓存了带有用户 A 会话 ID 的 Set-Cookie 标头。
  3. 用户 B 请求相同的页面,rack-cache 提供缓存的响应,包括带有用户 A 会话 ID 的 Set-Cookie 标头。

这两张票讨论了这个问题:https://github.com/rails/rails/issues/476https://github.com/rtomayko/rack-cache/pull/52

最后,在 rack-cache 1.2 的发行说明中提到了这个问题:https://github.com/rtomayko/rack-cache/blob/master/CHANGES

还要注意,即使您不使用 cookie 会话存储,会话 ID 仍然存储在 cookie 中,因此即使您不使用饼干店。

希望这会有所帮助。

约翰内斯

【讨论】: