Rails 为重复的 JSON 请求自动更新 CSRF 令牌

Posted

技术标签:

【中文标题】Rails 为重复的 JSON 请求自动更新 CSRF 令牌【英文标题】:Rails automatically update CSRF token for repeat JSON request 【发布时间】:2016-02-29 17:45:14 【问题描述】:

我有一个包含许多远程表单的单页 ROR 应用程序。我的问题是,在非幂等请求 Rails 更改 CSRF 令牌并使嵌入在页面元数据中的令牌无效之后。如果页面没有刷新,那么重复的非幂等请求就会失败。

例如,当通过 POST 提交的远程表单因验证错误而失败并重新提交表单时,它会因 InvalidAuthenticityToken 错误而失败。

我认为这个问题很常见,Rails 可以默认处理它,但显然不是。

【问题讨论】:

你能让 CSRF 令牌持久化吗?每个用户会话只需要一个 CSRF 令牌,而不是每个“不安全”请求。 @SilverlightFox 保留 CSRF 令牌不会降低应用程序的安全性吗?攻击者是否有可能捕获 CSRF 令牌并在发出请求时使用它? 不是,see here。 BREACH attack 存在一些风险,但是您最好禁用通过 HTTPS 进行的任何压缩。 刚刚也添加了我自己的答案:security.stackexchange.com/a/106826/8340 【参考方案1】:

我的解决方案,这里有什么陷阱吗?:

application_controller.rb:

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  # callback to set CSRF TOKEN for non-idempotent Ajax request
  after_action :add_csrf_token_to_json_request_header

  private

  def add_csrf_token_to_json_request_header
    if request.xhr? && !request.get? && protect_against_forgery?
      response.headers['X-CSRF-Token'] = form_authenticity_token
    end
  end
end

application.js:

//= require jquery2
//= require jquery_ujs
//= require turbolinks=

$( document ).ajaxComplete(function( event, xhr, settings ) 
  header_token = xhr.getResponseHeader('X-CSRF-Token');
  if (header_token) $('meta[name=csrf-token]').attr('content', header_token)
);

【讨论】:

谢谢。经过一天的搜索解决方案后,我遇到了这个问题,它对我有用。我的应用程序禁用了 turbolinks,因为我有单页应用程序,我需要自己处理 csrf,否则我会收到 ActionController::InvalidAuthenticityToken 错误

以上是关于Rails 为重复的 JSON 请求自动更新 CSRF 令牌的主要内容,如果未能解决你的问题,请参考以下文章

Rails:将 API 请求限制为 JSON 格式

内容类型设置为 application/json 的 Ajax 请求被 Rails 解释为文本

RSpec在请求后发送原始JSON参数

Rails 为 json api 请求返回不正确的 MIME 类型(仅在测试中)

如何在rails中处理来自应用程序控制器的无效真实性令牌json请求

rails 为 jquery-ui 自动完成小部件格式化 json.jbuilder