鉴于会话密钥和秘密,我们如何解密Rails cookie?

我有一个关于Rails如何处理cookie加密/解密的问题。

我在config / environment.rb中有这个

config.action_controller.session = { :session_key => [some key], :secret => [some secret] } 

这在config / environment / production.rb等人:

  ActionController::Base.session_options[:session_domain] = [some domain] 

到目前为止,这么好 – 只要我的所有Rails应用程序具有相同的session_key和秘密,并且在同一个域中,它们都可以使用相同的cookie。

但是,一位同事现在有一个JSP应用程序(在同一个域上),他想用它来读取我设置的cookie。

因此,给定一个秘密和加密的cookie值,我们如何解密它以获取该cookie的内容?

(文档似乎表明这是默认的单向SHA1加密 – http://caboo.se/doc/classes/CGI/Session/CookieStore.html – 但是我的Rails应用程序将如何读取内容单向加密的cookie?)

提前感谢任何提示/指示/见解,

如果直接从存储在应用程序数据库中的会话数据中提取session.data字段(如果在environment.rb文件中使用active_record_store)

 config.action_controller.session_store = :active_record_store 

…这里是你解码它并返回哈希的方法:

 Marshal.load(ActiveSupport::Base64.decode64(@session.data)) 

……或者在Rails中> = 3.2(感谢Chuck Vose)

 Marshal.load(Base64.decode64(@session.data)) 

它根本没有加密。

Rails使用HMAC-SHA1加密cookie数据,这与您怀疑的单向SHA1加密不同(请参阅维基百科有关HMAC的文章以获得解释)。 加密由ActiveSupport::MessageVerifier类完成(源代码相当可读)。 这是一个基于测试Rails应用程序的示例:

 secret = 'b6ff5a9c3c97bf89afe9a72e6667bafe855390e8570d46e16e9760f6394' + '4ab05577b211ec2f43f6c970441518f0241775499bde055078f754c33b62f68ba27ca' cookie = "_test_session=BAh7CCIYdXNlcl9jcmVkZW50aWFsc19pZGkGIhV1c2VyX2NyZW" + "RlbnRpYWxzIgGAMzBlODkxZDQ2MWZhNjFkMDFmNzczMmJjNDdjMjIwZGFjMTY2NWEwNDMwZ" + "DVjMmUxOWY5MDFjMjQ5NWQ4OTM1OGZlMzE3NzRiZTFiZjM1ZTVlZDY2ZGUzYTkwOWZjZTgw" + "NTFlNGUxZWI0MTUzYTRjODZiMGZmMzM3NzliM2U3YzI6D3Nlc3Npb25faWQiJTgxNzk0Yjd" + "kN2IxYzRjMDE0M2QwOTk5NTVjZjUwZTVm--25c8f3222ab1be9f2394e2795a9f2557b06d0a92" session = cookie.split('=').last verifier = ActiveSupport::MessageVerifier.new(secret, 'SHA1') verifier.verify(session) 

这应该返回您期望的会话哈希。 要在Java中实现这一点,您的同事将不得不复制ActiveSupport::MessageVerifier#verify方法。 源代码位于您的gems目录(我系统上的/usr/lib/ruby/gems/1.8/gems ),位于activesupport-2.3.5/lib/active_support/message_verifier.rb

以下是如何在Rails 4中解密会话cookie

 def decrypt_session_cookie(cookie) cookie = CGI.unescape(cookie) config = Rails.application.config encrypted_cookie_salt = config.action_dispatch.encrypted_cookie_salt # "encrypted cookie" by default encrypted_signed_cookie_salt = config.action_dispatch.encrypted_signed_cookie_salt # "signed encrypted cookie" by default key_generator = ActiveSupport::KeyGenerator.new(config.secret_key_base, iterations: 1000) secret = key_generator.generate_key(encrypted_cookie_salt) sign_secret = key_generator.generate_key(encrypted_signed_cookie_salt) encryptor = ActiveSupport::MessageEncryptor.new(secret, sign_secret) encryptor.decrypt_and_verify(cookie) end 

http://big-elephants.com/2014-01/handling-rails-4-sessions-with-go/

默认情况下,Rails(版本4之前)不会加密会话cookie,它只会签名。 要加密它们,您需要执行以下操作:

 ActionController::Base.session_store = EncryptedCookieStore 

有多个插件提供这种加密function。

因此,如果您没有专门使用加密存储,则所有Java代码需要做的是validationcookie签名并解码cookie。 正如Alex在他的回答中所说,你需要复制ActiveSupport::MessageVerifier#verify ,并与Java应用程序共享密钥。 这既validation和解码cookie。

如果您不想validation签名(我不建议),您可以使用Midwire的Base64解码方法来查看会话哈希。 在Ruby中,这是:

 Marshal.load(ActiveSupport::Base64.decode64(the_cookie_value)) 

我知道这是旧的,但希望这有助于某人!

(更新:问题与Rails有关3.从Rails 4开始,会话cookie默认加密。)

我编写了一个Ruby gem来处理由Rails应用程序管理的cookie。 阅读它的源代码,您可以了解它的工作原理,并可能将其移植到Java,以便您的JSP应用程序可以使用它:

https://github.com/rosenfeld/rails_compatible_cookies_utils

它是一个包含约150行代码的单个文件,它还处理仅签名的cookie值,并负责签名/加密和validation/解密,而您似乎只关心解密。 这是解密的方法:

https://github.com/rosenfeld/rails_compatible_cookies_utils/blob/master/lib/rails_compatible_cookies_utils.rb#L41-L52

值得一提的是,除了密钥和秘密之外,您还需要知道使用哪个序列化程序。 它曾经是Marshal,但似乎新生成的应用程序的默认值现在是JSON。 如果使用Marshal,那么将该代码转换为Java可能会很棘手,因为您必须找到实现Ruby的Marshal #load的库。