代码之家  ›  专栏  ›  技术社区  ›  Joe Holloway

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

  •  3
  • Joe Holloway  · 技术社区  · 16 年前

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

    我考虑过两种方法:

    1. 将信息存储在会话cookie中。这种方法的问题是,我需要设置会话cookie的过期时间,这样做的副作用是在浏览器关闭时导致用户的登录会话不会过期。
    2. 将信息存储在数据库中,并将检索密钥存储在客户端的cookie中。我担心性能问题,因为这需要额外的查询,可能还需要一些反序列化来检索数据。由于性能原因,Rails似乎不久前从ActiveRecordStore切换了默认值: https://web.archive.org/web/20120102024844/https://www.ryandaigle.com/articles/2007/2/21/what-s-new-in-edge-rails-cookie-based-sessions

    2 回复  |  直到 6 年前
        1
  •  0
  •   joshsz    16 年前

    为什么不直接使用非会话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]))
    
        2
  •  0
  •   ajreal    14 年前

    它实际上是从基于文件的会话存储更改为基于cookie的会话存储,而不是从ActiveRecord。我可能错了,但我相信ActiveRecord是一个可行的选择,为网络农场或分布式设置时,基于文件的存储是默认的。自从引入了基于cookie的存储之后,web场场景就不再是问题了,因为它存储在客户端。今天,ActiveRecord仍然是一个可行的选择,当您希望减少每个请求中传输的数据开销(使用ActiveRecord意味着您只传输会话id)时,或者如果您想要一个集中的会话设置,您需要存储比cookie所允许的更多的数据量。

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