无法在 Rails + React App 中验证 CSRF 令牌

Posted

技术标签:

【中文标题】无法在 Rails + React App 中验证 CSRF 令牌【英文标题】:Can't verify CSRF Token in Rails + React App 【发布时间】:2018-03-29 11:21:38 【问题描述】:

我有一个使用 Rails 和 React 的应用程序。 rails 部分的 AJAX 工作正常,但我在 React 中有一些使用 AJAX 的组件,并且错误发生在通过 React 组件的 AJAX 请求中。

我收到以下错误:

2017-10-17T15:36:26.933083+00:00 app[web.1]: [14b2fc9e-80b7-490f-b905-
5be9f6839c5b] Started POST "/quiz_submissions" for 162.158.165.188 at 2017-10-17 15:36:26 +0000
2017-10-17T15:36:26.935109+00:00 app[web.1]: [14b2fc9e-80b7-490f-b905-
5be9f6839c5b] Processing by QuizSubmissionsController#create as JSON
2017-10-17T15:36:26.935151+00:00 app[web.1]: [14b2fc9e-80b7-490f-b905-5be9f6839c5b]   Parameters: "quiz_submission"=>"quiz_problem_id"=>"21", "checked_option_ids"=>["88"]
2017-10-17T15:36:26.935688+00:00 app[web.1]: [14b2fc9e-80b7-490f-b905-5be9f6839c5b] Can't verify CSRF token authenticity.
2017-10-17T15:36:26.936459+00:00 app[web.1]: [14b2fc9e-80b7-490f-b905-5be9f6839c5b] Completed 422 Unprocessable Entity in 1ms (ActiveRecord: 0.0ms)
2017-10-17T15:36:26.937451+00:00 app[web.1]: [14b2fc9e-80b7-490f-b905-5be9f6839c5b]   
2017-10-17T15:36:26.937485+00:00 app[web.1]: [14b2fc9e-80b7-490f-b905-5be9f6839c5b] ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):

我已经尝试通过将 CSRF 令牌添加到我的 main.js 来在 ajax 标头中添加 CSRF 令牌

$.ajaxSetup(
  beforeSend: function(xhr) xhr.setRequestHeader('X-CSRF-Token', 
  $('meta[name="csrf-token"]').attr('content')),
);

这在我的本地机器上完全可以正常工作,但在生产环境(Heroku)上会出现同样的错误。

另外,我还尝试在 React 组件内的单个 ajax 请求的标头中添加 CSRF 令牌,如下所示:

$.ajax(
      dataType: 'JSON',
      type: 'POST',
      url: '/quiz_submissions',
      context: this,
      headers: 
          'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
      ,
      data: 
        ...
        
      

这种方法在本地也可以正常工作,但在生产中会出现相同的 Can't verify CSRF token authenticity. 错误。

我的头部有<%= csrf_meta_tags %>,我的application.js也有//= require jquery_ujs

知道为什么它不能在 Heroku 的生产环境中运行吗?

【问题讨论】:

几件事;首先,Rails 在幕后做了一些魔术来自动将 CSRF 令牌应用于非获取请求。所以你不需要做任何这些。它不起作用的事实表明您的应用程序上的 csrf 标记设置不正确。我猜这是因为有一个异步登录页面(使用 react 构建,而不是传统的 html 表单),因此登录时没有设置 CSRF 标签。您可以通过在登录后使用从登录帖子收到的信息手动更新 CSRF 标签来解决此问题。 我正在使用登录表单的设计。而且我还有其他使用 ajax 的部分(不在反应组件中),并且在那些非反应 ajax 请求上我没有收到任何 Can't verify CSRF token authenticity. 错误,所以我认为这可能不是登录页面的问题,可以吗? 试试这个 => https://***.com/questions/7203304/warning-cant-verify-csrf-token-authenticity-rails#answer-43138944 @7urkm3n 我在.ajax.ajaxSetup 中都尝试了beforeSendheaders。它在我的本地机器上完美运行,没有错误,并且 ajax 请求成功。但是在我将它部署到 heroku 之后,我在 heroku 日志上得到了相同的 Can't verify CSRF token authenticity. @Swojeet 你用什么版本的rails? 【参考方案1】:

可能,这应该有效。

LINK HERE !!!


使用 jquery.csrf (https://github.com/swordray/jquery.csrf)。

Rails 5.1 或更高版本

$ yarn add jquery.csrf
//= require jquery.csrf

Rails 5.0 或之前的版本

source 'https://rails-assets.org' do
  gem 'rails-assets-jquery.csrf'
end
//= require jquery.csrf

源代码

(function($) 
  $(document).ajaxSend(function(e, xhr, options) 
    var token = $('meta[name="csrf-token"]').attr('content');
    if (token) xhr.setRequestHeader('X-CSRF-Token', token);
  );
)(jQuery);

【讨论】:

嘿@7urkm3n,我添加了jquery.csrf,当我在本地预编译我的资产并将其推送到heroku 时,ajax 工作。但是,如果在 heroku 上预编译资产,它会显示:Sprockets::FileNotFound: couldn't find file 'jquery.csrf' with type 'application/javascript' 我在 ruby​​ buildpack 和预编译资产成功之前将 nodejs buildpack 添加到 heroku,但随后我得到相同的 Can't verify CSRF token authenticity. 错误。 你是如何在本地安装的? 你的意思是jquery.csrf?我跑了yarn add jquery.csrf 并将//= require jquery.csrf 包含在我的application.js 中。我删除了在 ajax 请求中具有 CSRF 令牌的标头,它在本地和 heroku 上都可以工作,但是在 Heroku 上预编译资产时抛出了这个错误:Sprockets::FileNotFound: couldn't find file 'jquery.csrf' with type 'application/javascript'

以上是关于无法在 Rails + React App 中验证 CSRF 令牌的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Rails / Webpacker / React 应用程序中处理图像?

在 Heroku 上使用 Rails API 部署 Create-React-App

无法验证令牌类型错误 React App

我无法使用 React_on_Rails gem 注册组件

成功的 Firebase 身份验证后 React Native App 无法导航

使用 Rails 和 React 时如何在标头中获取 JWT 令牌