ActionDispatch::Cookies 未设置 Set-Cookie header 作为响应,但 response.set_cookie 设置
ActionDispatch::Cookies not setting Set-Cookie header in response but response.set_cookie does
我有一个 Rails 5 API 的应用程序,我想在 JSON 请求的响应中发送 cookie。当我使用 ActionDispatch::Cookies 在请求的响应中设置 cookie 时,它不会在响应中设置 Set-Cookie
header。尽管 response.set_cookie
确实有效。
我还测试了在应用程序控制器中创建一个 after_action
挂钩,我看到的是 Set-Cookie
header 不存在于 response.headers 中,但 cookies['name_of_cookie'] 存在。我还想问的一个问题是这些 cookies(ActionDispatch::Cookies) 什么时候设置 header 作为响应?它发生在机架中吗?
要求
- 我们想在 CORS 请求中设置 cookie。
- 我们要为所有来源设置 cookies
已经实施的内容
- 客户端发送请求
withCredentials
- 在响应中存在
Access-Control-Allow-Credentials: true
和 Access-Control-Allow-Origin: <origin (request.headers['origin'])>
- 因为它是 Rails API 我们在应用程序中包含以下中间件的唯一应用程序
config.middleware.use ActionDispatch::Cookies
config.middleware.use ActionDispatch::Session::CookieStore, key: '_namespace_key'
问题
- 为什么 ActionDispatch::Cookies 不起作用但 response.set_cookie 起作用?
- ActionDispatch::Cookies 何时设置 header 响应?它发生在 rails 应用程序中的任何
after
回调挂钩中,还是发生在机架中?因为直到 applicaton_controller 中的 after_action
,header 才出现。
奇怪
- 在开发环境和我的本地机器上它可以工作,但在生产环境中不行。是不是跟cookie的
domain
设置有关系?我还在生产中使用安全和 httponly cookie,但在开发中只使用 httponly。
我在这里错过了什么?我花了几天时间寻找问题,但找不到解决方法。任何线索都会非常有帮助。谢谢
编辑 1
cookies[@name.to_sym] = {
value: @value,
expires: @expire,
httponly: true,
same_site: 'None',
secure: false # It works when I set it to false but doesn't work with `true` in production. In development env it works with either one.
}
response.set_cookie(
@name.to_sym,
value: @value,
expires: @expire,
httponly: true,
secure: true
)
我观察到一件事。如果我在 cookie 中设置 secure: false
,那么它可以在生产中使用,但不能用于 secure: true
。另一方面,secure: true
在生产中与 response.set_cookie 一起工作。
我的 request.protocol 是 HTTP。如果请求协议是 HTTP 并且配置了 secure: true
选项,ActionDispatch::Cookies 是否有可能甚至不设置 cookie。
但我认为 secure: true
是针对客户端的。就像如果 cookie 是安全的,那么浏览器只会通过 https 协议发送它。我错过了什么?
我明白了这种行为的原因。实际上,其他团队在生产环境中部署了 application gateway
。这导致 Rails 服务器收到最初为 HTTPS 的 HTTP 请求。
现在我已将 cookie 标记为 secure: true
,如果协议是 HTTP,ActionDispatch::Cookies 似乎甚至不会发送 cookie 来响应请求。它只会在协议为 HTTPS 时发送。如果我通过 secure: false
禁用安全,那么它可以工作,或者如果我禁用应用程序网关,那么它可以与 ActionDispatch::Cookie.
一起工作
这似乎很奇怪,因为 secure
是一个客户端属性,但是从 ActionDispatch::Cookies 的行为来看,如果协议是 HTTP 并且安全设置为,它甚至不会从服务器发送 cookie是的。
虽然我没有找到任何关于此行为的文档,但这就是它的工作方式。
遇到了类似的问题,但 cookie 被作为 Header 传递。问题出在 session_expiry
上,它是在启动时设置的 (session_store.rb
),因为它来自不同的 Time.zone
,这迫使 cookie 在创建后立即被浏览器删除。
相反,我使用了 expire_after: 20.minutes
,这使它对我有用。
在此发布,in-case 任何人都面临类似问题。
我有一个 Rails 5 API 的应用程序,我想在 JSON 请求的响应中发送 cookie。当我使用 ActionDispatch::Cookies 在请求的响应中设置 cookie 时,它不会在响应中设置 Set-Cookie
header。尽管 response.set_cookie
确实有效。
我还测试了在应用程序控制器中创建一个 after_action
挂钩,我看到的是 Set-Cookie
header 不存在于 response.headers 中,但 cookies['name_of_cookie'] 存在。我还想问的一个问题是这些 cookies(ActionDispatch::Cookies) 什么时候设置 header 作为响应?它发生在机架中吗?
要求
- 我们想在 CORS 请求中设置 cookie。
- 我们要为所有来源设置 cookies
已经实施的内容
- 客户端发送请求
withCredentials
- 在响应中存在
Access-Control-Allow-Credentials: true
和Access-Control-Allow-Origin: <origin (request.headers['origin'])>
- 因为它是 Rails API 我们在应用程序中包含以下中间件的唯一应用程序
config.middleware.use ActionDispatch::Cookies
config.middleware.use ActionDispatch::Session::CookieStore, key: '_namespace_key'
问题
- 为什么 ActionDispatch::Cookies 不起作用但 response.set_cookie 起作用?
- ActionDispatch::Cookies 何时设置 header 响应?它发生在 rails 应用程序中的任何
after
回调挂钩中,还是发生在机架中?因为直到 applicaton_controller 中的after_action
,header 才出现。
奇怪
- 在开发环境和我的本地机器上它可以工作,但在生产环境中不行。是不是跟cookie的
domain
设置有关系?我还在生产中使用安全和 httponly cookie,但在开发中只使用 httponly。
我在这里错过了什么?我花了几天时间寻找问题,但找不到解决方法。任何线索都会非常有帮助。谢谢
编辑 1
cookies[@name.to_sym] = {
value: @value,
expires: @expire,
httponly: true,
same_site: 'None',
secure: false # It works when I set it to false but doesn't work with `true` in production. In development env it works with either one.
}
response.set_cookie(
@name.to_sym,
value: @value,
expires: @expire,
httponly: true,
secure: true
)
我观察到一件事。如果我在 cookie 中设置 secure: false
,那么它可以在生产中使用,但不能用于 secure: true
。另一方面,secure: true
在生产中与 response.set_cookie 一起工作。
我的 request.protocol 是 HTTP。如果请求协议是 HTTP 并且配置了 secure: true
选项,ActionDispatch::Cookies 是否有可能甚至不设置 cookie。
但我认为 secure: true
是针对客户端的。就像如果 cookie 是安全的,那么浏览器只会通过 https 协议发送它。我错过了什么?
我明白了这种行为的原因。实际上,其他团队在生产环境中部署了 application gateway
。这导致 Rails 服务器收到最初为 HTTPS 的 HTTP 请求。
现在我已将 cookie 标记为 secure: true
,如果协议是 HTTP,ActionDispatch::Cookies 似乎甚至不会发送 cookie 来响应请求。它只会在协议为 HTTPS 时发送。如果我通过 secure: false
禁用安全,那么它可以工作,或者如果我禁用应用程序网关,那么它可以与 ActionDispatch::Cookie.
这似乎很奇怪,因为 secure
是一个客户端属性,但是从 ActionDispatch::Cookies 的行为来看,如果协议是 HTTP 并且安全设置为,它甚至不会从服务器发送 cookie是的。
虽然我没有找到任何关于此行为的文档,但这就是它的工作方式。
遇到了类似的问题,但 cookie 被作为 Header 传递。问题出在 session_expiry
上,它是在启动时设置的 (session_store.rb
),因为它来自不同的 Time.zone
,这迫使 cookie 在创建后立即被浏览器删除。
相反,我使用了 expire_after: 20.minutes
,这使它对我有用。
在此发布,in-case 任何人都面临类似问题。