5

Rails 中是否有任何规定允许来自站点的所有 AJAX POST 请求在没有authentity_token 的情况下通过?

我有一个调用控制器方法的 Jquery POST ajax 调用,但我没有在其中放入任何真实性代码,但调用成功。

我的 ApplicationController 确实有“request_forgery_protection”,我已经改变了

config.action_controller.consider_all_requests_local

在我的环境/development.rb 中为 false

我还搜索了我的代码以确保我没有超载 ajaxSend 来发送真实性令牌。

是否有某种机制可以禁用检查?现在我不确定我的 CSRF 保护是否有效。

我正在使用 Rails 2.3.5。

为清晰起见更新:

function voteup(url, groupid){
      $.ajax({
        type: "POST",
        url: "/groups/" + groupid + "/submissions/voteup",
        data: "url=" + url,
        dataType: 'text',
        success: function(data){
          var counter = "vote_" + url;
          $('#vote_' + url.cleanify()).text(" " + data + " ");
        }
      });
    };

我有一个链接,然后有一个调用上述函数的'href:

<a href='javascript:voteup(param1,param2)'>...</a>
4

2 回答 2

7

这里一个可能的情况是您使用 jQuery 来序列化一个普通的 Rails 表单......它包括序列化的身份验证令牌隐藏字段(Rails 将它们添加到所有表单)。

查看您正在提交的表单的生成源......您可能会看到

<input name="authenticity_token" type="hidden" value="somethinghere...." />

您可以做的另一件事是检查日志以查看authentity_token 字段是否在请求参数中。

于 2010-06-17T06:59:08.343 回答
3

在你的布局视图中添加这个:app/views/layouts/(something).html.erb

<% if protect_against_forgery? %>
 <script type="text/javascript" charset="utf-8">
  //<![CDATA[
   window._auth_token_name = "#{request_forgery_protection_token}";
   window._auth_token = "#{form_authenticity_token}";
  //]]>
 </script>
<% end %>

在你的 application.js 中:

$.ajaxSetup({
  'beforeSend': function(xhr) {xhr.setRequestHeader("Accept", "text/javascript")}
});

$(document).ready(function() {
 //  All non-GET requests will add the authenticity token
 //  If not already present in the data packet
 $("body").bind('ajaxSend', function(elm, xhr, s) {
   if (s.type == "GET") return;
   if (s.data && s.data.match(new RegExp("\\b" + window._auth_token_name + "="))) return;
   if (s.data) {
  s.data = s.data + "&";
  } else {
   s.data = "";
   // if there was no data, $ didn't set the content-type
   xhr.setRequestHeader("Content-Type", s.contentType);
  }
  s.data = s.data + encodeURIComponent(window._auth_token_name) + "=" + encodeURIComponent(window._auth_token);
 });

在你的 application_controller.rb 添加这个以确保 IE/SAFARI 接收正确的接受标头:

 def correct_safari_and_ie_accept_headers
    ajax_request_types = [ 'text/javascript', 'application/json', 'text/xml']
        request.accepts.sort!{ |x, y| ajax_request_types.include?(y.to_s) ? 1 : -1 } if request.xhr?
 end

这可确保接受标头默认为text/javascriptapplication/jsontext/xml代替默认值text/html

现在您可以执行常规的 AJAX 调用了。它将传递身份验证令牌。还要确保仅在 CDATA 脚本标记之后包含 application.js,因为它需要两个全局变量window._auth_token_namewindow._auth_token.

希望这可以帮助!干杯:)

于 2010-06-17T07:37:26.590 回答