ruby-on-rails - ActionDispatch::Cookies 没有跨域设置
问题描述
我有一个与后端 Rails API 交互的前端 React SPA。在生产中,前端有一个域名mysecretsite.com
,而后端与mysecretsite.io
我正在使用ActionDispatch::Cookies在浏览器中设置访问令牌,以便用户可以使用该令牌发出后续请求。
cookies.signed[:access_token] = { value: 'tmp_token_string', httponly: true, domain: :all }
当 React SPA 和 Rails API 都在一台计算机上的本地开发中运行时,它可以按预期工作。
在我分别在不同的服务器上部署了 React SPA 和 Rails API 之后,我注意到浏览器中没有正确设置 cookie。
我可以在开发模式下重现此类问题,我将 React SPA 放置在同一 LAN 内的另一台计算机上。
我曾尝试使用 React SPA 的字符串为开发环境或生产环境或只是配置ActionDispatch::Cookies参数,但它没有改变任何东西。domain
IP:Port
%w(.mysecretsite.com .mysecretsite.io)
nil
我的 cookie 设置中可能会遗漏什么?
控制器/application_controller.rb
class ApplicationController < ActionController::API
include ActionController::Cookies
end
配置/应用程序.rb
module RailsApp
class Application < Rails::Application
config.load_defaults 5.2
config.api_only = true
config.middleware.use ActionDispatch::Cookies
end
end
24 小时后,我有一些额外的信息:
我查看了 Chrome 浏览器的响应标头。在使用 Rails API 在同一台计算机上运行的 React SPA 中,access_token
cookie 已正确设置。这是响应标头:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS, HEAD
Access-Control-Allow-Origin: http://192.168.12.40:27511
Access-Control-Expose-Headers:
Access-Control-Max-Age: 1728000
Cache-Control: max-age=0, private, must-revalidate
Content-Type: application/json; charset=utf-8
ETag: W/"ebd48cd3b0ac4fa7ba23a4d40b8508a2"
Vary: Origin
X-Request-Id: 9aa588f0-8569-b1ca-901945962e87
X-Runtime: 0.064807
当 React SPA 在同一 LAN 内的另一台计算机上运行时,access_token
cookie 没有设置,就像在生产中发生的那样。这是响应标头:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS, HEAD
Access-Control-Allow-Origin: http://192.168.12.50:27511
Access-Control-Expose-Headers:
Access-Control-Max-Age: 1728000
Cache-Control: max-age=0, private, must-revalidate
Content-Type: application/json; charset=utf-8
ETag: W/"ebd48cd3b0ac4fa7ba23a4d40b8508a2"
Vary: Origin
X-Request-Id: 9aa588f0-8569-b1ca-901945962e87
X-Runtime: 0.059074
在这两种情况下,Set-Cookie
标头都丢失了,但其中一个成功设置了 cookie,而另一个失败。
解决方案
我自己弄清楚了这个问题。我只是无法将.com
域分配给 React API,而将.io
域与 Rails API 关联。
问题是
您需要至少两个级别的域相同才能使用 cookie
在开发环境中,当 React SPA 和 Rails API 运行在不同的主机上时,我的解决方法是分别为两个应用程序分配一个通用的本地域名。
首先,编辑/etc/hosts
为:
192.168.12.40 mydevsite.com
192.168.12.10 api.mydevsite.com
其次,在 Rails API 应用程序中,将mydevsite.com:27511
作为附加源添加到文件config/initializers/cors.rb
中。并重启 Rails API 生效。
最后,更新 React SPA 和浏览器中的相关请求 URL。
24 小时后
我可以确认该问题在生产环境中也已解决,其中 Rails API 配置了新域名api.mysecretsite.com
但是,我仍然不知道为什么官方文档有一个设置示例domain: %w(.example.com .example.org)
,以及它们呈现什么样的用例。
推荐阅读
- flutter - Flutter 通过更改父级的参数来重新初始化有状态的小部件
- android - lateinit 属性 androidInjector 尚未初始化 Dagger 2
- javascript - JavaScript:很难诊断错误
- googlebot - 是否有可能让 fail2ban 忽略谷歌?
- python - 训练数据集时出现索引超出范围错误
- algorithm - 以伪随机方式将数字 1 映射到 1 的有效方法?
- r - 在 R 中创建具有 3 个解释变量的箱线图
- mysql - mysql:在 1 中组合 3 个查询 - 分组依据
- php - 是一种在不同地方回显相同数据而不需要多个 for eaches 的方法
- reactjs - EmailJS + React Hooks + 'preventDefault' 的问题