Rails 3.1 - 忽略 CSRF?

Posted

技术标签:

【中文标题】Rails 3.1 - 忽略 CSRF?【英文标题】:Rails 3.1 - CSRF ignored? 【发布时间】: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 令牌与当前会话在交响乐中进行验证,该会话在另一个标头中维护(应该自动发送,但在您的情况下可能不是)。 看我的回答:***.com/questions/15239818/… 【参考方案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 不是为了防止点击劫持,它完全是一种单独的攻击,另一个网站可以让用户点击一个链接,该链接通过用户的会话在您的网站上执行操作。

【讨论】:

以上是关于Rails 3.1 - 忽略 CSRF?的主要内容,如果未能解决你的问题,请参考以下文章

忽略 URL CSRF Guard

如何在spring boot项目中忽略特定URL的spring security CSRF

小记一次被忽略的恶CSRF刷收藏漏洞

Rails 5 忽略 /lib 类?

Rails 3 AJAX请求真实性令牌被忽略

rails :dependent=>:destroy 被忽略