Cookie 未在 SPA 的浏览器中设置为 API 通信

Cookies are not set in browser in SPA to API communication

我正在设置 React SPA (www.mysite.com) 和 Rails API (api.mysite.com) 应用程序。当我使用相同的 URL 名称时,一切都按预期工作,但是当 URL 名称不同时,Web 浏览器不会设置站点 cookie。由于缺少 cookie,CSRF 验证当然也会失败。因此,例如,如果 SPA 应用程序在 localhost 上运行并且 Rails API 应用程序在 localhost:3000 上运行一切正常,问题仅在我使用预期的 DNS 名称时出现。

听起来像是一个 CORS 问题,但我已经好几天找不到问题所在了……

这是我的配置:

Rails这边我用的是rack-corsrubygem

config/initializers/cors.rb

Rails.application.config.middleware.insert_before 0, Rack::Cors do
   allow do
     origins 'localhost’,  'www.mysite.com',

     resource '*',
       headers: :any,
       credentials: true,
       methods: [:get, :post, :put, :patch, :delete, :options, :head]
   end
end

Rails.application.config.action_controller.forgery_protection_origin_check = false

在 React 端我有 axios 配置如下:

src/App.js

axios.defaults.xsrfCookieName = "CSRF-TOKEN";
axios.defaults.xsrfHeaderName = "X-CSRF-Token";
axios.defaults.withCredentials = true;

当 React App 启动时,它会向 API 后端发出 GET 请求以获取 CSRF 令牌以备后用。同时浏览器应该设置站点 cookie。

    axios
        .get("/sessions/csrf_token", {
          headers: { "Content-Type": "application/json"
          },
        })
        .then(response => {
          // do stuff
          });
        });

设置站点 cookie 和缺少站点 cookie 的两种情况下,响应 headers 看起来都一样

我还可以看到 cookie 已发送到浏览器,但它们在 Cookie 部分下不见了

非常感谢任何关于我在这里可能遗漏的想法!!! 谢谢!!

UPDATE:

我还应该提到我的 session 配置文件设置为允许子域

config/initializers/session_store.rb

Rails.application.config.session_store :cookie_store, key: '_mysite_session', expire_after: 8.hours, domain: :all, tld_length: 2

可能是我的 cookies 配置出了问题,但我不知道应该查看哪里以及应该检查哪些其他设置。

这是我使用 localhost 时我的 Cookies 窗格的屏幕截图,并且 cookies 按预期保留在浏览器中:

当我使用 www.mysite.comapi.mysite.com 名称时,右侧的窗格是空的。

我一直在调查这个问题,我认为这可能与您所看到的有关:

Share cookie between subdomain and domain

显然,如果您未在 set-cookie header 中指定域,则该 cookie 将被视为 "host only"。所以你可能必须让它看起来像:

Set-Cookie: name=value; domain=mydomain.com

我确信这可以通过 Axios 实现。

我遇到了同样的问题。 我解决了这个问题,为 cookie 设置了一个域。

在 ApplicationController 中,当您设置 CSRF-TOKEN 时,请执行以下操作

cookies["CSRF-TOKEN"] = {
  value: form_authenticity_token,
  domain: ".mysite.com"
}

并且在 config/application.rb 中也添加域 config.middleware.use ActionDispatch::Session::CookieStore, domain: ".mysite.com"

希望这个回答对您有所帮助