如何从 Heroku 中托管的 Rails API 应用程序在浏览器中设置 cookie,该应用程序在 Netlify 中托管的 React 应用程序中运行前端?
Posted
技术标签:
【中文标题】如何从 Heroku 中托管的 Rails API 应用程序在浏览器中设置 cookie,该应用程序在 Netlify 中托管的 React 应用程序中运行前端?【英文标题】:How can I set cookies in a browser from a Rails API app hosted in Heroku running the frontend in a React app hosted in Netlify? 【发布时间】:2021-12-18 02:50:37 【问题描述】:我使用 Rails --api --db:postgres 标志构建了一个 API。我使用 React create app 在另一个应用程序中构建了前端。
Rails 6.1.4.1,Ruby 3.0.2p107 Rails 应用部署在 Heroku 中 Netlify 中的 React 应用 我使用会话 cookie 来存储用户 ID,并使用 CSRF 令牌来提高安全性(主要用于学习目的)通过在端口 localhost:3001 中运行 rails 服务器并在端口 localhost:3000 中做出反应,这两个 cookie 都已在我的本地环境中按预期正确设置。 p>
但是,在 herokuapp.com 中部署 Rails 并在 netlify.app 中部署 React 后,虽然浏览器在响应中收到了 cookie,但它并没有设置它们。
这是我在浏览器中看到的:
Cookies Response
我的 Cors.rb 文件已正确设置以允许我的 netlify 域连接到服务器,例如 my-domain.netlify.app 和 https://my-domain.netlify.app .
在设置 cookie 时,我尝试了所有可能的设置组合,但似乎没有任何效果。目前它看起来像这样:
def set_csrf_cookie
cookies['CSRF-TOKEN'] =
value: form_authenticity_token,
domain: my-app.herokuapp.com,
same_site: :None,
secure: true
end
在我的 cors.rb 文件中,第一行有这段代码:
Rails.application.config.action_controller.forgery_protection_origin_check = false
我的 application.rb 文件有这个配置:
config.api_only = true
config.middleware.use ActionDispatch::Cookies
config.middleware.use ActionDispatch::Session::CookieStore
我的应用程序控制器如下所示:
class ApplicationController < ActionController::API
before_action :set_csrf_cookie
include ActionController::Cookies
include ActionController::RequestForgeryProtection
protect_from_forgery with: :exception
include Response
include ExceptionHandler
def cookie
'ok'
end
private
def set_csrf_cookie
cookies['CSRF-TOKEN'] =
value: form_authenticity_token,
domain: 'my-app.herokuapp.com',
same_site: :None,
secure: true
end
end
我通过从 App.js 组件调用 API 来设置 cookie。调用是对 path '/' 进行的,该路径被路由到 application#cookie,您可以在上面的应用程序控制器代码中看到它。
我知道我能够连接 API,因为一些不需要 CSRF 令牌的端点工作正常。
我感觉我的问题与托管在 2 个不同域中的应用有关。我也认为这可能是前端问题,而不是后端问题。
任何成功完成此操作的人的帮助将不胜感激。
【问题讨论】:
【参考方案1】:经过大量研究和大量测试,我发现我的 cookie 无法正常工作的主要原因是现在浏览器处理第三方 cookie 的方式。 事实证明,Safari 和 Chrome 默认会阻止它们。我还错过了跨站点 cookie 实际上并不存在的事实。
我写了一篇文章解释了我是如何解决这个问题的:https://medium.com/@ArturoAlvarezV/use-session-cookies-to-authenticate-a-user-with-a-rails-api-backend-hosted-in-heroku-on-one-domain-f702ddf8c07
基本上,我的解决方案非常简单,从浏览器中移除跨站点跟踪保护,使用名为“rails_same_site_cookie”的 Ruby on Rails gem,并将这一行添加到我的 production.rb 文件中:
config.action_dispatch.cookies_same_site_protection = :None
这对我有用。此行默认将 rails 中的所有 cookie 转换为 SameSite:None
和 Secure:true
,包括 Rail 的内置会话 cookie。
我的开发人员工具不会在我的 cookie 面板中显示 cookie,但现在每次我向 API 发出请求时,它们都会设置并与我的凭据一起发送。
【讨论】:
以上是关于如何从 Heroku 中托管的 Rails API 应用程序在浏览器中设置 cookie,该应用程序在 Netlify 中托管的 React 应用程序中运行前端?的主要内容,如果未能解决你的问题,请参考以下文章
Django 有没有像 Ruby on Rails 有 Heroku 这样的东西
Ruby on Rails 中的 Sendgrid / 电子邮件发送问题(托管在 Heroku 上)