Javascript 使用 AJAX 向 Rails 发送真实性令牌的正确方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7560837/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 02:44:13  来源:igfitidea点击:

Proper way to send an Authenticity Token with AJAX to Rails

javascriptjqueryruby-on-railsajaxauthenticity-token

提问by Trip

This works but gets stopped because it lacks an authenticity token:

这有效但被停止,因为它缺乏真实性令牌:

$(".ajax-referral").click(function(){
  $.ajax({type: "POST", url: $(this).parent("form").attr("action"), dataType: "script"});
  return false;
});

So I tried adding it like so:

所以我尝试像这样添加它:

$(".ajax-referral").click(function(){
  $.ajax({type: "POST", url: $(this).parent("form").attr("action") + "?&authenticity_token=" + AUTH_TOKEN, dataType: "script"});
  return false;
});

And it passes the auth_token correctly as a param, but seems to lose the rest of my form.

并且它正确地将 auth_token 作为参数传递,但似乎丢失了我表单的其余部分。

Anyways to accomplish both sending the form data that works, and the authenticity token as well?

无论如何要同时发送有效的表单数据和真实性令牌?

This is a rails environment. And I have this in my head.

这是一个 Rails 环境。我脑子里有这个。

= javascript_tag "var AUTH_TOKEN = '#{form_authenticity_token}';" if protect_against_forgery?

Things I've tried

我尝试过的事情

1.

1.

= hidden_field :authenticity_token, :value => form_authenticity_token

2.

2.

$.ajax({type: "POST", url: $(this).parent("form").attr("action"), dataType: "script", authenticity_token: AUTH_TOKEN});

3.

3.

// Always send the authenticity_token with ajax
$(document).ajaxSend(function(event, request, settings) {
    if ( settings.type != 'GET' ) {
        settings.data = (settings.data ? settings.data + "&" : "")
            + "authenticity_token=" + encodeURIComponent( AUTH_TOKEN );
    }
});

采纳答案by Muhammad Adeel Zahid

Actually, you are reading the actionattribute of form and sending a post ajax request to it. to send form data you have to submit the form or you can serialize the form data and send it in ajax request like

实际上,您正在读取action表单的属性并向其发送 post ajax 请求。要发送表单数据,您必须提交表单,或者您可以序列化表单数据并在 ajax 请求中发送它,例如

$(".ajax-referral").click(function(){
  $.ajax({
      type: "POST", 
      url: $(this).parent("form").attr("action") + "?&authenticity_token=" + AUTH_TOKEN, 
      data:$(this).parent("form").serialize(),
      dataType: "script"
      });
  return false;
});

Doing this will serialize your form data and send it along with ajax request and authenticity token is already being sent via query string

这样做将序列化您的表单数据并将其与 ajax 请求一起发送,并且真实性令牌已经通过查询字符串发送

回答by omdel

This token also already appears in one of the "meta" tags in the head of the application.html.erb layout file by default if you have the following ERB at the top:

如果顶部有以下 ERB,则默认情况下,此标记也已出现在 application.html.erb 布局文件头部的“meta”标记之一中:

<%= csrf_meta_tag %>

That ERB roughly renders to:

该 ERB 大致呈现为:

<meta content="abc123blahblahauthenticitytoken" name="csrf-token">

You can then grab it using jQuery with the following code:

然后,您可以使用 jQuery 使用以下代码获取它:

var AUTH_TOKEN = $('meta[name=csrf-token]').attr('content');

回答by Adam Grant

None of these worked for me until I set the X-CSRF-Tokenvalue on the request header via JS like this:

这些都不适合我,直到我X-CSRF-Token通过 JS设置请求标头的值,如下所示:

request.setRequestHeader('X-CSRF-Token', token)

tokenof course, being the CSRF token. I got this from the <meta name="csrf-token">tag and did not use encodeURIComponent()

token当然,作为CSRF令牌。我从<meta name="csrf-token">标签上得到了这个,但没有使用encodeURIComponent()

Updatesince this is proving useful to some

更新,因为这证明对某些人有用

So all in all:

所以总而言之:

var token = document.querySelector('meta[name="csrf-token"]').content
request.setRequestHeader('X-CSRF-Token', token)

回答by Yavor Ivanov

Thanks!

谢谢!

Just to clarify for the more common use.

只是为了澄清更常见的用途。

You need the js tag with var AUTH_TOKEN in your head. Should be something like this.

您需要头脑中带有 var AUTH_TOKEN 的 js 标记。应该是这样的。

<%= csrf_meta_tag %>
<%= javascript_tag "var AUTH_TOKEN = '#{form_authenticity_token}';" if protect_against_forgery? %>

And then simply put your authenticity_token=AUTH_TOKEN in the ajax data if you don't need to use parent(form) or something like this.

然后,如果您不需要使用 parent(form) 或类似的东西,只需将您的真实性_token=AUTH_TOKEN 放在 ajax 数据中。

$.ajax({
  type: 'post',
  dataType:'text',
  data: "user_id="+user_id+"&authenticity_token="+AUTH_TOKEN,
  url:'/follow/unfollow'
})

Thanks to the guys above for sharing this knowledge!

感谢上面的人分享这些知识!

回答by carnator

I just ran into this issue but I tried this approach in my application.js file:

我刚刚遇到了这个问题,但我在 application.js 文件中尝试了这种方法:

$(document).ajaxSend(function(e, xhr, options) {
  if (options.data == null) {
    options.data = {};
  }
  options.data['authenticity_token'] = token;
});

This is the original question where I got the idea: ajaxSend Question

这是我想到的原始问题:ajaxSend Question

回答by BishopRook

You could include the AUTH_TOKEN in the form itself, as a hidden input.

您可以在表单本身中包含 AUTH_TOKEN 作为隐藏输入。

<input type="hidden" name="AUTH_TOKEN">1234abcd</input>

回答by Rustam A. Gasanov

In Rails 5.1+ a CSRF token is automatically appended if you use a built-in RailsJS helper for AJAX requests(from rails-ujs), example:

在 Rails 5.1+ 中,如果您Rails对 AJAX 请求(来自rails-ujs)使用内置JS 助手,则会自动附加 CSRF 令牌,例如:

Rails.ajax({
  url: "/your/url",
  type: "POST",
  data: "a=1&b=2",
  success: function(data) {
    console.log(data);
  }
});

This library also provides you a helper to get CSRF token manually if you need it with:

如果您需要,该库还为您提供了一个帮助程序来手动获取 CSRF 令牌:

Rails.csrfToken();

回答by wondersz1

Simply using form_tag automatically includes CSRF token parameter. Rails supports "Unobtrusive Javascript" meaning that the form will still be submitted via AJAX. Controller actions support "respond_to" block, and you can use .js.erb extension to make changes on the web page in response to form submit.

只需使用 form_tag 自动包含 CSRF 令牌参数。Rails 支持“Unobtrusive Javascript”,这意味着表单仍将通过 AJAX 提交。控制器动作支持“respond_to”块,您可以使用 .js.erb 扩展名在网页上进行更改以响应表单提交。