【问题标题】:Difference in cookie content using Sinatra session & Rack::Session::EncryptedCookie使用 Sinatra 会话和 Rack::Session::EncryptedCookie 的 cookie 内容差异
【发布时间】:2013-06-25 19:47:12
【问题描述】:

我正在学习 Sinatra 框架并开发登录系统。我遇到了两种使用 cookie 的方法。

一个简单的 Sinatra 内置方式:

enable :sessions
set :session_secret, 'random-key'

这种方法在登录时会产生以下 cookie 内容(使用 session.inspect 获取输出):

{"session_id"=>"6be0b9a31831604ba51114d265ba952482e0b2da6ced6c54e15ebe7f212858ca", 
"tracking"=>{"HTTP_USER_AGENT"=>"b8c1e8f89eeaea0b825bed0d811f0c7678e98c74", 
"HTTP_ACCEPT_ENCODING"=>"a0bfc876d68fe7aea700da5ea8925abac6f2f794", 
"HTTP_ACCEPT_LANGUAGE"=>"dd065ed263c67d799f943ab6c39b55c5e008cbb5"}, 
"csrf"=>"b480324f510e4f391d15cee8236a8fb74a5aaa5ce2f9ad38e4dbb025a823b16e",    
"name"=>"john"}

另一种方法是使用加密的 cookie:

require 'sinatra'
require 'encrypted_cookie'

use Rack::Session::EncryptedCookie, :secret => "random-key"

但是这种方法在登录时会产生以下 cookie 内容(这里也使用了session.inspect):

{:name=>"john"}

为什么enable :sessions 会创建一个包含所有这些信息的大 cookie 以及为什么需要它(尤其是那些 HTTP_... 部分?)因为 Rack::Session::EncryptedCookie 没有生成任何信息。

您是否认为应该首选使用 enable :sessions,因为它具有 csrf 令牌和会话 ID?还是你觉得Rack::Session::EncryptedCookie已经加密了就够了?

我安装了以下版本的 gem:

encrypted_cookie (0.0.4)
rack (1.5.2)
rack_csrf (2.4.0)
sinatra (1.4.3)
thin (1.5.1)

如果您需要更多信息,请告诉我...

【问题讨论】:

    标签: ruby cookies sinatra session-cookies rack


    【解决方案1】:

    据我所知,在 Sinatra 中使用 Rack::Session::Cookie 并将 session_secret 写入环境变量时,已创建的会话在项目部署后不会销毁。我认为这是单页应用程序的风险。

    【讨论】:

      【解决方案2】:

      因为启用:sessions 时,Sinatra 将使用rack-protection 中间件。它使 cookie 更大但更安全。

      相关sn-p:

      def setup_default_middleware(builder)
        builder.use ExtendedRack
        builder.use ShowExceptions       if show_exceptions?
        builder.use Rack::MethodOverride if method_override?
        builder.use Rack::Head
        setup_logging    builder
        setup_sessions   builder
        setup_protection builder
      end
      
      def setup_sessions(builder)
        return unless sessions?
        options = {}
        options[:secret] = session_secret if session_secret?
        options.merge! sessions.to_hash if sessions.respond_to? :to_hash
        builder.use session_store, options
      end
      
      def setup_protection(builder)
        return unless protection?
        options = Hash === protection ? protection.dup : {}
        options = {
          img_src:  "'self' data:",
          font_src: "'self'"
        }.merge options
      
        protect_session = options.fetch(:session) { sessions? }
        options[:without_session] = !protect_session
      
        options[:reaction] ||= :drop_session
      
        builder.use Rack::Protection, options
      end
      
      • sessions? 如果启用 :sessions 则返回 true
      • session_store 默认为Rack::Session::Cookie

      Rack::Session::EncryptedCookie的区别

      也就是说,如果你想将Rack::Session::EncryptedCookierack-production一起使用,可以通过以下方式轻松完成:

      enable :sessions
      set :session_store, Rack::Session::EncryptedCookie
      

      仅供参考,由于encrypted_cookie 缺少某些功能(秘密轮换、自定义序列化程序等)并且不再处于维护状态,因此我制作了another one 来替换它。

      希望对你有帮助。

      【讨论】:

        【解决方案3】:

        因为Rack::Session::EncryptedCookie 要求您的密钥长度至少为 16 位。在 README 中,他们建议使用 OpenSSL 生成密钥,如下所示:

        ruby -ropenssl -e "puts OpenSSL::Random.random_bytes(16).inspect"
        

        如果您打开检查器,您会看到一个名为“rack.session”的 cookie,其内容已被混淆。

        【讨论】:

        • 是的。我知道 :)。但我的问题是您是否更喜欢enable :sessions,因为它正在生成会话 ID 和 csrf 令牌以及所有额外的东西?还是您更喜欢Rack::Session::EncryptedCookie,因为它是加密的并且不需要那些添加?
        • 您在使用任何其他中间件吗?执行enable :sessions 然后检查会话会给我一个类似于Rack::Session::EncryptedCookie 的输出。就个人而言,我使用Rack::Session::Cookie 作为中间件并在其上设置秘密(从环境变量加载)。
        • 嗯。在使用enable :sessions 方法时,我没有使用任何其他中间件。顺便说一句,我编辑了问题以包含所需宝石的版本。与您相比,我可能有不同版本的宝石。有什么线索吗?
        猜你喜欢
        • 2016-03-06
        • 2013-09-06
        • 2013-08-05
        • 1970-01-01
        • 2011-05-14
        • 2023-03-24
        • 2012-11-14
        • 2011-12-03
        • 2010-10-31
        相关资源
        最近更新 更多