为什么rails不断发回Set-Cookie标头?

Tom*_*vol 6 cookies session ruby-on-rails amazon-elb

我遇到了弹性负载均衡器和关于cookie的会话缓存以及会话在rails和客户端之间混淆的问题.部分问题是,rails几乎在每个请求上都添加了一个"Set-Cookie"标头,并且会话ID.如果客户端已经发送了session_id,并且它匹配rails将要设置的session_id ..为什么rails会不断告诉客户"哦是啊..你的会话ID是......"

geo*_*ock 12

摘要: Set-Cookie几乎每个响应都设置了标题,因为

  1. 默认会话存储将尝试将会话数据写入已访问会话的任何请求的加密cookie(要么从中读取或写入它),
  2. 即使纯文本值没有,加密值也会改变,
  3. 加密发生在它到达负责检查cookie值是否已更改以避免冗余Set-Cookie头的代码之前.

纯文本cookie

在Rails中,ActionDispatch::Cookies中间件负责Set-Cookie根据a的内容编写响应头ActionDispatch::Cookies::CookieJar.

正常行为是您所期望的:如果cookie的值没有从请求的Cookie标头中更改,并且未更新到期日期,则Rails将不会Set-Cookie在响应中发送新标头.

这是通过条件来处理的,CookieJar#[]=其中将已经存储在cookie jar中的值与正在写入的新值进行比较.

加密的cookie

为了处理加密的cookie,Rails提供了一个ActionDispatch::Cookies::EncryptedCookieJar类.

EncryptedCookieJar依靠ActiveSupport::MessageEncryptor提供加密和解密,它使用一个随机的初始化向量每次它被称为时间.这意味着即使给出相同的纯文本字符串,它几乎可以保证返回不同的加密字符串.换句话说,如果我解密我的会话数据,然后重新加密它,我最终会得到一个与我开始的字符串不同的字符串.

EncryptedCookieJar并没有做太多的事情:它包装了一个常规的CookieJar,只是在数据进入时提供加密,并在数据恢复时进行解密.这意味着该CookieJar#[]=方法仍然负责检查cookie的值是否已更改,并且它甚至不知道已经给出的值是加密的.

这两个属性EncryptedCookieJar解释了为什么设置加密cookie而不更改其值将始终产生Set-Cookie标题.

会话商店

Rails提供不同的会话存储.它们中的大多数ActionDispatch::Session::CookieStore将会话数据存储在服务器上(例如,在memcached中),但是默认 - EncryptedCookieJar用于将所有数据存储在加密的cookie中.

ActionDispatch::Session::CookieStore继承一个#commit_session?方法from Rack::Session::Abstract::Persisted,它确定是否应该设置cookie.如果会话被加载,那么答案几乎总是"是的,设置cookie".

正如我们已经看到的那样,在会话被加载但没有改变的情况下,我们仍然会得到一个不同的加密值,因此也就是一个Set-Cookie标题.