在Rails中存储持久会话数据而不影响正常会话到期

时间:2010-02-14 04:37:14

标签: ruby-on-rails session

我想为每个浏览器存储一些持久性数据(用户设置),并且不希望登录使用该站点。实现这一目标的方法是什么?

我考虑了两种方法:

  1. 将信息存储在会话cookie中。这种方法的问题是我需要在会话cookie上设置过期时间,这会导致用户的登录会话在浏览器关闭时不会过期。
  2. 将信息存储在数据库中,并将检索密钥存储在客户端的cookie中。我担心性能问题,因为这需要额外的查询和可能的一些反序列化来检索数据。由于性能原因,Rails似乎暂时将其默认值从ActiveRecordStore切换回来:http://ryandaigle.com/articles/2007/2/21/what-s-new-in-edge-rails-cookie-based-sessions
  3. 实现这一目标的推荐方法是什么?

2 个答案:

答案 0 :(得分:0)

为什么不使用非会话cookie?您可以指定它在客户端上保留的时间等。请参阅http://api.rubyonrails.org/classes/ActionController/Cookies.html

如果您担心用户搞乱了cookie数据,您可以使用这样的技术加密cookie数据(取自http://www.neeraj.name/blog/articles/834-how-cookie-stores-session-data-in-rails):

cookie_data = {:foo => "bar"}
digest = 'SHA1'
secret = 'my_encryption_secret'
data = ActiveSupport::Base64.encode64s(Marshal.dump(cookie_data))
digest_value = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new(digest), secret, data)
escaped_data_value = Rack::Utils.escape(data)
final_output = "#{escaped_data_value}--#{digest_value}"
cookies[:user_data] = final_output

以后读取cookie数据:

Marshal.load(ActiveSupport::Base64.decode64(cookies[:user_data]))

答案 1 :(得分:0)

它实际上是从基于文件的会话存储更改为基于cookie的会话存储 - 而不是从ActiveRecord。我可能错了,但我相信当基于文件的存储是默认的时,ActiveRecord是Web场或分布式设置的可行选项。由于引入了基于cookie的存储,因此Web场景已成为非问题,因为它存储在客户端。今天,当你想减少每个请求中传输的数据的开销时,使用ActiveRecord意味着你只传输session_id,或者你想要一个集中的会话设置。

我发现在使用ActiveRecord会话存储时,速度对我来说不是一个因素。在基于cookie的会话中,您通常会限制存储在会话变量中的内容,因此它们往往是用于在数据库中查找数据的令牌。如果数据不需要在会话之外持久化,那么将对象存储在会话中而不仅仅是一个令牌是可行的,因为无论如何你都要在数据库中找到关联的记录。如果要检索的对象涉及昂贵的检索操作,并且在会话的生命周期中需要它,那么将该对象存储在会话中而不仅仅是一个令牌是有意义的,并且只有在会话时才会命中一次db最初成立。

Cookie很棒,但请记住,用户可以在需要时删除它们,加密或不加密。随着隐私问题的不断增加,以及为有条件地阻止cookie的浏览器和清理cookie的软件提供了相当多的插件,您可能需要权衡使用cookie与数据库支持的会话的优缺点。

@joshsz提出了使用非会话cookie来保存会话之外的数据的好处。请记住,会话的生命周期有限。