【问题标题】:Adding X-CSRF-Token header globally to all instances of XMLHttpRequest();将 X-CSRF-Token 标头全局添加到 XMLHttpRequest() 的所有实例;
【发布时间】:2014-08-03 11:18:42
【问题描述】:

我正在使用第三方库,它会生成原始的 XMLHttpRequestnew XMLHttpRequest

这绕过了我的 CSRF 保护并被我的 Rails 服务器击落。

有没有办法在实例化时将预定义的 CSRF 令牌 ($('meta[name=csrf-token]').attr('content')) 全局添加到 XMLHttpRequest 的所有实例?

【问题讨论】:

标签: javascript ajax security xmlhttprequest csrf


【解决方案1】:

你可以把ajax的open()方法包装起来打开,然后马上设置header:

(function() {
    var op = XMLHttpRequest.prototype.open;
    XMLHttpRequest.prototype.open = function() {
        var resp = op.apply(this, arguments);
        this.setRequestHeader('X-CSRF-Token', $('meta[name=csrf-token]').attr('content'));
        return resp;
    };
}());

【讨论】:

    【解决方案2】:

    我推荐intercept callssend 方法:

    (function() {
        var send = XMLHttpRequest.prototype.send,
            token = $('meta[name=csrf-token]').attr('content');
        XMLHttpRequest.prototype.send = function(data) {
            this.setRequestHeader('X-CSRF-Token', token);
            return send.apply(this, arguments);
        };
    }());
    

    这不会在实例化时添加标头,而是在发送请求之前添加。您也可以拦截对 new XMLHttpRequest() 的调用,但这无济于事,因为您需要等待添加标头直到调用 open

    您可能还希望对请求的目标 URL 进行测试,以便仅在调用自己的 api 时添加标头。不这样做可能会在其他地方泄漏令牌,甚至可能会破坏不允许此标头的跨域 CORS 调用。

    【讨论】:

    • 我在打开后就这样做了,这样它就可以被破坏了,但是我想有 6 个,另外 6 个......
    • @dandavis:最初我也想拦截open,但我不只是想重复您回答中的代码。就像我看到你的帖子弹出一样,你得到了 +1 :)
    • 智者相通。我可以问一下,你对这种模式 100% 没问题吗?尽管我看不到伤害,但对我来说感觉有点冒险/肮脏。
    • 99%。使用内置对象时的风险与往常一样:它们的实现方式可能与您想象的不同。从特定于实例的方法到不可写的.send 属性,再到不继承.applysend 方法,所有怪癖都是可能的(众所周知,旧的IE 在它们的DOM 中有这样的怪癖)。但是,在现代浏览器中这将起作用,它们尊重 Web-IDL 规范关于如何在 javascript 中实现 HTML5 api。
    【解决方案3】:

    如果您需要独立于 Jquery 的解决方案,您可以使用:

      (function() {
          var send = XMLHttpRequest.prototype.send,
              token = document.getElementsByTagName('meta')['csrf-token'].content;
          XMLHttpRequest.prototype.send = function(data) {
              this.setRequestHeader('X-CSRF-Token', token);
              return send.apply(this, arguments);
          };
      }());
    

    【讨论】:

      猜你喜欢
      • 2020-08-25
      • 2017-05-14
      • 2014-04-11
      • 2021-05-14
      • 2016-10-03
      • 2016-03-29
      • 2021-12-29
      • 2019-02-06
      • 2018-11-03
      相关资源
      最近更新 更多