【问题标题】:Cookies are not set in browser in SPA to API communication在 SPA 到 API 通信的浏览器中未设置 Cookie
【发布时间】:2020-07-21 09:09:02
【问题描述】:

我正在设置 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-cors ruby​​ gem

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 令牌以供以后使用。同时浏览器应该设置站点cookies。

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

当站点 cookie 设置和缺失时,两种情况下的响应标头看起来相同

我还可以看到 cookie 已发送到浏览器,但它们在 Cookies 部分下丢失了

非常感谢您对我在这里遗漏的任何想法! 谢谢!!

更新:

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

config/initializers/session_store.rb

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

我的 cookie 配置可能有其他问题,但我不知道在哪里查看以及应该检查哪些其他设置。

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

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

【问题讨论】:

  • 这有点像在黑暗中拍摄,但是您是否尝试过在您的 rack-cors 配置中指定没有 WWW 的第二个域?无论如何,我们是否可以获取您的浏览器 cookie 窗格以及您正在谈论的那些真实域的源代码的图片?
  • @sevensidemarble 我试过没有 www 的域没有成功。一般来说,如果 CORS 设置以任何方式错误配置,axios 根本不会得到有效响应。在我的情况下,我没有看到任何错误,并且 API 调用返回了有效的 JSON 响应。唯一的问题是我的 cookie 窗格是空的。让我为帖子本身添加一个更新,并附上我希望 cookie 窗格看起来像的屏幕截图
  • 我想我可能已经想通了,请在下面查看我的答案。

标签: ruby-on-rails cookies axios cross-domain csrf


【解决方案1】:

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

Share cookie between subdomain and domain

显然,如果您未在 set-cookie 标头中指定域,则 cookie 将被视为“仅限主机”。所以你可能必须让它看起来像:

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

我确信这对 Axios 是可行的。

【讨论】:

  • 所以我的问题是 Rails 不会使用 cookie 发送域信息。这应该由上面的 Rails.application.config.session_store 行处理,但由于某种原因它没有发生。我可以使用域属性手动设置自定义 cookie,然后它会出现在 Cookies 窗格中。现在我需要弄清楚为什么 Rails 没有在全球范围内这样做......谢谢你的帮助!
【解决方案2】:

我遇到了同样的问题。 我解决了这个问题,为 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"

希望这个回答对你有帮助

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-26
    • 2021-09-30
    • 2019-07-25
    • 2023-03-16
    • 1970-01-01
    • 2021-07-22
    • 2020-10-07
    相关资源
    最近更新 更多