对js请求执行Rails ActionController::InvalidCrossOriginRequest



我知道这在SO上已经提过几次了,但我无法取得进展。我在Rails 5.0.7.2上。

我每天都会被抛出数百次ActionController::InvalidCrossOriginRequest。Rollbar说这主要是由Bingbot引起的,它在我的用户注册模式中,来自Devise。这是一个GET请求,路径为/users/sign_up

注意:这不是一个表单。这是一个模式,它只是询问用户您希望如何注册?电子邮件、Fb、谷歌认证等

基本上,我的网站上有一些javascript操作,比如reddit或stackoverflow upvote。我不是在这些链接上使用remote: true,而是我有一个$.ajax调用,它处理向上投票,如下所示:

var token = document.querySelector('meta[name="csrf-token"]').content;
$.ajax({
// For the upvote, type will be POST
type: $this.data('method'),
beforeSend: function(xhr) {
xhr.setRequestHeader('X-CSRF-Token', token)
},
url: $this.data('url'),
success: function(data) {
// Some cleanup...
}
}); 

一旦一个注销的访问者试图投赞成票,它就会触发ajax请求,然后该请求被暂停(未经授权(并重定向,如下所示:

Started POST "/upvotes/toggle_vote"
Processing by UpvotesController#toggle_vote as */*
Completed 401 Unauthorized in 1ms (ActiveRecord: 0.0ms)

Started GET "/users/sign_up"
Processing by RegistrationsController#new as */*

这是我覆盖的Devise控制器:

class RegistrationsController < Devise::RegistrationsController
def new
# ... other code        
respond_to do |format|
format.js   { render layout: false }
format.html { respond_with self.resource }
end
end
end

在CCD_ 5内部我有CCD_;你想怎么报名"情态动词

我尝试了什么:

  • 我不认为通过添加protect_from_forgery except: :new来解决它是正确的答案(就像在类似的问题中提出的那样(,因为这本质上是不安全的。

  • 我尝试根据这个重新排序respond_to格式,但这使得注册模式无法打开。

  • 我试图在respond_to块中加入format.any { raise ActionController::RoutingError.new("Not Found") }catch-all,但这并没有修复错误。

  • 正如您在上面的$.ajax调用中看到的,我甚至尝试设置X-CSRF-Token标头。

顺便说一句,完整的错误文本是:

ActionController::InvalidCrossOriginRequest: Security warning: an embedded <script> tag on another site requested protected JavaScript. If you know what you're doing, go ahead and disable forgery protection on this action to permit cross-origin JavaScript

有什么想法吗?

可能是因为UpvotesController#toggle_vote重定向到RegistrationsController#new并从POST更改为GET,所以真实性令牌丢失了吗?

几个想法:

  1. 你不应该自己放csrf令牌,jquery rails或rails uj(我不确定你用的是哪一个(都会为你做这件事;对于轨道uj,您需要使用Rails.ajax方法

  2. 没有将POST重定向到GET并保留原始POST头,这意味着您确实在GET请求中丢失了csrf令牌(但是,您通常不会在GET请求发送或需要csrf令牌,所以请检查您为什么要这样做(。

您需要发送一个真实性令牌,其中包含修改服务器中资源的ajax请求(post/put/patch/delete(。通常,rails会为您添加它作为表单中的隐藏字段。

将其添加到表单中就可以了:

<% hidden_field_tag :authenticity_token, form_authenticity_token %>

对我来说,这似乎是一个CORS问题,就像错误表明我对嵌入的javascript进行了API调用,该javascript位于与服务器上定义的域不同的域中。这会触发CORS错误。通常要修复CORS错误,您需要在允许的域列表中添加一个标题Access Control Allow Origin和网站的域。您可以使用rack-cors-gem轻松做到这一点:https://github.com/cyu/rack-cors

在Rails5中,我发现

config.action_view.embed_authenticity_token_in_remote_forms = true

避免了同域远程调用的CORS问题,但在Rail 6中似乎没有效果。

相关内容

  • 没有找到相关文章

最新更新