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-cors
rubygem
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.com
和 api.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"
希望这个回答对您有所帮助
我正在设置 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
rubygem
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.com
和 api.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"
希望这个回答对您有所帮助