我用Rails--API--db:postgres标志构建了一个API。我在另一个应用程序中使用React创建应用程序构建了前端。
- Rails 6.1.4.1、Ruby 3.0.2p107
- Rails应用程序部署在Heroku
- React应用程序,在Netlify中
- 我使用会话cookie来存储用户id和CSRF令牌,以提高安全性(主要用于学习目的(
通过在端口localhost:3001中运行rails服务器并在端口localhost:3000进行响应,两个cookie都已在本地环境中正确设置并达到预期效果。
然而,在herokuapp.com中部署Rails并在netlify.app中部署React之后,尽管浏览器在响应中接收到cookie,但它并没有设置它们。
这就是我在浏览器中看到的:
Cookie响应
我的Cors.rb文件设置正确,允许我的netlify域连接到服务器,就像我的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。调用是对路径'/'进行的,该路径被路由到应用程序#cookie,您可以在上面的应用程序控制器代码中看到。
我知道我能够连接API,因为一些不需要CSRF令牌的端点工作正常。
我有一种感觉,我的问题与应用程序托管在两个不同的域有关。我还认为这可能是一个前端问题,而不是后端问题。
任何成功完成这项工作的人的帮助都将不胜感激。
经过大量的研究和测试,我发现我的cookie不起作用的主要原因是因为现在浏览器处理第三方cookie的方式。事实证明,Safari和Chrome默认情况下会阻止它们。我还忽略了跨站点cookie实际上并不存在的事实。
我写了一篇文章解释我是如何解决这个问题的:https://medium.com/@ArturoAlvarezV/use-session-cookies-authenticate-auser-with-arails-pi-backend hosted-in-heroku-on-on-domain-f702ddf8c07
基本上,我的解决方案非常简单,使用RubyonRails gem"Rails_same_site_cookie"从浏览器中删除跨站点跟踪保护,并将此行添加到我的production.rb文件中:
config.action_dispatch.cookies_same_site_protection = :None
这对我来说很有用。这条线默认情况下将rails中的所有cookie都转换为SameSite:None
和Secure:true
,包括Rail的内置会话cookie。
我的开发人员工具不会在我的cookie面板中显示cookie,但现在每次我向API发出请求时,它们都会被设置并与我的凭据一起发送。