在XMLHttpRequest()的所有实例中全局添加X-CSRF-Token头

Adding X-CSRF-Token header globally to all instances of XMLHttpRequest();

本文关键字:全局 添加 X-CSRF-Token 实例 XMLHttpRequest      更新时间:2023-09-26

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

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

是否有一种方法可以在实例化时全局添加预定义的CSRF令牌($('meta[name=csrf-token]').attr('content'))到XMLHttpRequest的所有实例?

我建议拦截对send方法的调用:

(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调用。

您可以将ajax open()方法包装为打开,然后立即设置标题:

(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;
    };
}());

如果您需要独立于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);
      };
  }());