我有一个前端react spa与后端rails api交互。在生产中,前端有一个域名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。
我曾尝试用react spa的
domain
字符串为开发环境配置ActionDispatch::Cookies参数,或为生产环境配置IP:Port
参数,或仅仅为%w(.mysecretsite.com .mysecretsite.io)
配置nil
参数,但它没有改变任何东西。在我的cookie设置中可能会错过什么?
控制器/应用程序控制器.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中,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
在这两种情况下,都缺少
access_token
头,但其中一个成功设置了cookie,而另一个失败。 最佳答案
我自己解决了这个问题。我只是不能将.com
域分配给react api,而将.io
域与rails api相关联。
问题是
为了使用cookies,您需要至少有两个域级别是相同的
如Cookies across multiple TLDs?所述
在开发环境中,当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
但是,我仍然不知道为什么the official documentation有一个设置示例
domain: %w(.example.com .example.org)
,以及它们呈现的是什么样的用例。关于ruby-on-rails - ActionDispatch::Cookie未跨域设置,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56911413/