protect_from_forgery&不引人注目的Javascript

时间:2009-04-08 19:41:17

标签: jquery ruby-on-rails ajax

我在我的Rails网站上有一些javascript进行ajax调用:

$.ajax({type: "PUT", url: url, data: { dummy: data }, complete: function(data) {}});

当Rails获取它时,它会抛出ActionController::InvalidAuthenticityToken错误。如果可能的话,我想保留那里的protect_from_forgery内容...但是我怎么能从javascript文件中传递auth令牌呢?

任何人都可以帮助我吗?

2 个答案:

答案 0 :(得分:21)

在你的布局中,在任何其他JS运行之前添加它:

<script>
  function authToken() {
    return '<%= form_authenticity_token if protect_against_forgery? -%>';
  }
</script>

authToken被编码为一个函数,因此您不太可能意外地使用其他JavaScript覆盖它。

或者,从Rails 3开始,身份验证令牌嵌入为<meta>标记,您可以阅读:

<script>
  function authToken() {
    return $('meta[name="csrf-token"]').attr('content');
  }
</script>

在主JS中,您可以调用authToken(),它会将您的真实性标记作为字符串返回到Ajax调用中。例如,使用jQuery:

$.ajax({
  type: 'PUT',
  url:  url,
  data: {
    foo: bar,
    authenticity_token: authToken()
  },
  complete: function(data) {}
});

请注意,如果您使用Rails的内置form_for帮助程序,它会自动在隐藏输入中添加真实性标记。如果要发送所有表单的数据,包括隐藏的身份验证令牌,您只需使用:

var $form = $('form');
$.ajax({
  url:      $form.attr('action'),
  type:     $form.attr('method'),
              // "get" or "post"; overridden by Rails' hidden "_method"
              // input value, e.g., "put"
  data:     $form.serialize(),
              // Includes hidden "authenticity_token" and "_method" inputs
  complete: function(data) {}
});

当你已经编写了一个没有JS的表单时,这种模式通常很有用,而你正在添加一个不显眼的JS层,只需通过Ajax发送表单的数据。

答案 1 :(得分:3)

感谢上述解决方案。
我在我的网站中使用了一些不使用rails form_tag的标准表单,所以我只是将其添加为隐藏表单元素。

<form action="...">
    <%= hidden_field_tag 'authenticity_token', form_authenticity_token if protect_against_forgery? %>
    ... rest of form...
</form>

努力享受。