【问题标题】:Rails 3.1 - CSRF ignored?Rails 3.1 - 忽略 CSRF?
【发布时间】:2011-11-08 09:57:18
【问题描述】:

这是我的问题,

我有一个 rails 3.1 应用程序,我正在尝试发出 ajax 请求,但我收到警告消息 “警告:无法验证 CSRF 令牌真实性”...

在我的布局中,我有辅助方法 "csrf_method_tag",我添加了以下 javascript 代码(不知道是否真的需要):

$.ajaxSetup({
  beforeSend: function(xhr) {
    xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'));
  }
});

我的 Gemfile 包含 gem jquery-rails (>= 1.0.12),我需要 jquery 和 jquery-ujs 在我的 application.js 的顶部。

即使这样,消息仍然出现。我是不是忘记了什么?

感谢您的帮助。

【问题讨论】:

  • 有同样的问题 - 登录后,如果我更改页面(使用 devise 和 rpx 可连接 gem),我会注销。如果您解决了这个问题,请告诉我们
  • 在 AJAX 请求的标头中发送的 cookie 是否与在加载发出请求的页面的请求上发送的 cookie 相同? CSRF 令牌与当前会话在交响乐中进行验证,该会话在另一个标头中维护(应该自动发送,但在您的情况下可能不是)。

标签: jquery ruby-on-rails-3.1 csrf


【解决方案1】:

您可能甚至不需要在代码中使用它。默认情况下,jquery-rails gem 会自动为所有 Ajax 请求设置 CSRF 令牌。

【讨论】:

  • 我知道,但即使删除了 javascript 代码,CSRF 令牌似乎仍然被忽略...
  • 您是使用标准的rails form_forform_tag 助手,还是使用您自己的<form .....> HTML 标签?
  • 我没有使用表单...我使用请求来更新部分内容或获取一些 JSON。
【解决方案2】:

您是否尝试过使用带有真实性令牌的隐藏表单元素?

<input type="hidden" name="authenticity_token" value="<%= form_authenticity_token>" />

我遇到了同样的错误,并且解决了它。这是因为我没有使用内置的表单助手......

【讨论】:

  • 不行,还是不行……我必须在本周末之前解决这个问题,如果我发现了什么,我会告诉你……
【解决方案3】:

在没有表单的情况下对我有用的是在 ajax 数据负载中包含 &lt;%= form_authenticity_token %&gt; 的结果。所以我做了一些类似 tehprofessor 在 html 中建议的事情:

<input id="tokentag" type="hidden" name="authenticity_token" value="<%= form_authenticity_token %>" />

然后在javascript中:

tokentag = $('#tokentag').val()
submitdata = { "authenticity_token": tokentag, ...+whatever else you need to include+...}

然后用submitdata 调用$.ajax

【讨论】:

    【解决方案4】:

    我也遇到了同样的麻烦。我试图捕捉一个 javascript 事件(you_tube 播放器已完成)并将 Ajax 返回到我的服务器让我知道。我得到了:

    警告:无法验证 CSRF 令牌的真实性

    每当 jQuery ajax 调用访问我的服务器时。我在上面添加了您的代码修复

    $.ajaxSetup({
        beforeSend: function(xhr) {
            xhr.setRequestHeader('X-CSRF-Token',
                                 $('meta[name="csrf-token"]').attr('content'));
        }
    });
    

    而且效果很好。我认为唯一的区别在于我的布局

    <%= csrf_meta_tags %>
    

    而不是您在原始帖子中提到的 csrf_method_tag。
    所以谢谢你的修复,它在原始帖子中。

    【讨论】:

    • 不要在你的帖子中使用签名或标语。阅读the FAQ entry了解更多信息。谢谢!
    【解决方案5】:

    一个原因可能是您在加载文档之前进行了 AJAX 调用,因此 JQuery 无法获取 CSRF 令牌。

    【讨论】:

      【解决方案6】:

      直接在您的 AJAX 调用上执行此操作即可正常工作!

        $.ajax({
                  type: //method,
                  beforeSend: function(xhr){
                      xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))
                  },
                  url: //parameter,
                  dataType: 'html',
                  success: function(data, textStatus, jqXHR) {
                     // some code
                  }
        });
      

      【讨论】:

        【解决方案7】:

        问题是您需要在 Ajax POST 请求之后获取新令牌,因为一旦使用令牌,它就会失效。这是执行此操作的代码:

        在 Rails 中,每当发送 POST 回复时,将这些参数添加到响应中:

        def someMethod:
            result[:csrfParam] = request_forgery_protection_token
            result[:csrfToken] = form_authenticity_token
            render :json => result
        end
        

        现在在 JS 端,在每个 POST 方法的成功函数中都可以调用这个函数:

        var setCsrfToken = function(param, token) {
            if(param == null || token == null) {
                console.error("New CSRF param/token not present");
            }
            $("input[name='" + param + "']").val(token);
        }
        

        像这样:

        setCsrfToken(result["csrfParam"], result["csrfToken"]);
        

        此函数将重置所有 POST 表单中的所有authentity_token 参数,以便下一个请求具有有效的令牌。您需要确保在每个 POST 调用中都会发生这种情况,否则您将继续面临此问题。

        另外,CSRF 不是为了防止点击劫持,它完全是一种单独的攻击,另一个网站可以让用户点击一个链接,该链接通过用户的会话在您的网站上执行操作。

        【讨论】:

          猜你喜欢
          • 2015-11-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-07-15
          • 2012-11-19
          • 1970-01-01
          • 2012-02-26
          • 1970-01-01
          相关资源
          最近更新 更多