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

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

简介:几乎每个响应都设置了Set-Cookie标头,因为

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

纯文本cookie

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

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

这由CookieJar#[]=的条件处理, 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中),但ActionDispatch::Session::CookieStore使用EncryptedCookieJar将所有数据存储在加密的cookie中。

ActionDispatch::Session::CookieStoreinheritance了#commit_session? Rack::Session::Abstract::Persisted ,它确定是否应该设置cookie。 如果会话已加载,则答案几乎总是“是,设置cookie”。

正如我们已经看到的那样,在会话已加载但未更改的情况下,我们仍然会以不同的加密值结束,因此也就是Set-Cookie标头。

Interesting Posts