使用setRequestHeader制作xmlhttprequest时,为什么无法设置cookie和set-cookie标头?

时间:2013-03-04 09:26:37

标签: javascript html node.js cookies xmlhttprequest

我想知道为什么不能使用setRequestHeader设置 cookie 标头。是否有任何特定原因或只是它们是由浏览器本身添加的,所以这些标题被禁用了?有安全问题吗?

- 修改

我正在使用node.js并使用xmlhttprequest模块。以下是测试代码:

var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.withCredentials = true;
xhr.setRequestHeader('Cookie', "key=value");
xhr.send(null);

这里我需要设置cookie-header为node.js' xmlhttprequest不要显式添加cookie-header(如浏览器那样)。在尝试执行此操作时,xmlhttprequest会出现错误“Refused to set unsafe header”。

虽然我找到了补丁并成功发送了cookie标题。但是想知道为什么禁用它来设置cookie-header?无论我在哪里阅读,发现它是数据完整性和安全性所必需的,但在这种情况下可以违反什么安全性,在哪里都没有提到。我想评估这个数据完整性问题是否对node.js应用程序有效,如果我使用我的补丁。

7 个答案:

答案 0 :(得分:23)

我相信你会经历working draft并找到

  

上述标题由用户代理控制,以便让它控制   运输的那些方面。

首先,我们需要了解,这些是作为不同浏览器之间功能互操作性指南的标准。它不是针对浏览器的强制要求,因此浏览器由于不同的原因确实对该标准有不同程度的遵守。

其次,从技术上讲,您可以模拟用户代理,将您的程序视为浏览器,并且可以按照上述标准很好地设置这些值。

最后,意图禁止覆盖标头或为某些字段设置标头,例如Content-LengthCookie ethos secure design approach。这是为了阻止或至少试图阻止HTTP Request smuggling

答案 1 :(得分:14)

您可以禁用此行为:

var xhr = new XMLHttpRequest();
xhr.setDisableHeaderCheck(true);
xhr.open(...);
...

答案 2 :(得分:8)

众所周知,对于浏览器,需要谨慎管理cookie(以及其他属性)以防止第三方窃取用户会话(或其他数据)。这是浏览器的问题,以及访问运行任意Javascript的网站的不受控制的性质。

当然,任意代码执行的风险对于node.js来说风险很小或没有风险,因为你只运行一个你编写的脚本,它可能运行你计划的其他代码。

如果你看一下driverdan XMLHttpRequest.js的源代码,你会发现:

 // These headers are not user setable.   
 // The following are allowed but banned in the spec:   
 // * user-agent   
 var forbiddenRequestHeaders = [
    "accept-charset",
    "accept-encoding",
    "access-control-request-headers",
    "access-control-request-method",
    "connection",
    "content-length",
    "content-transfer-encoding",
    "cookie",
    "cookie2",
    "date",
    "expect",
    "host",
    "keep-alive",
    "origin",
    "referer",
    "te",
    "trailer",
    "transfer-encoding",
    "upgrade",
    "via"   ];

这回答了你的具体问题,为什么限制特别适用于用于node.js的这个脚本 - 编码器遵循规范(尽可能接近),尽管感觉它可能不是节点中所需的安全预防措施.js文件。不过,这个默认安全级别很容易修改。

正如robertklep指出的那样,您可以使用setDisableHeaderCheck方法禁用此默认预防措施。是的,这个最后一点确实对你的问题的答案做出了回答或做出了重大贡献,因为在你提出的问题中你曾说过:

I have found a patch and successfully able to send the cookie-header

我们现在发现你不需要那个补丁。

祝你好运!

答案 3 :(得分:4)

是的,它是数据完整性和安全性所必需的。要理解这一点,您必须了解cookie在HTTP请求方法中的作用。

Cookie在识别用户,浏览器,连接等方面非常重要,并且存储在Web浏览器中。 JavaScript允许您操作cookie,但不能操纵浏览器上的所有cookie。 请参阅HTTP cookies,这些仅由浏览器设置,因此用户不能滥用它(通过JavaScript)。

  

在支持的浏览器上,仅使用HttpOnly会话cookie   在传输HTTP(或HTTPS)请求时,从而限制访问   来自其他非HTTP API(例如JavaScript)。

当您发送xmlhttprequest时,它会读取HttpOnly cookie并通过Cookie标头发送到服务器。 现在,如果您执行xhr.setRequestHeader('Cookie', "key=value");,则试图篡改发送到服务器的cookie。 setRequestHeader会添加额外的key=value,这可能会影响所发送Cookie的完整性。

服务器使用这些来验证用户(会话,电子邮件帐户或任何帐户)。这实际上允许服务器防止滥用cookie来访问服务器。

答案 4 :(得分:2)

文档提到这样做是为了保护数据的完整性。 http://www.w3.org/TR/XMLHttpRequest/#the-setrequestheader%28%29-method

  

上述标题由用户代理控制,以便让它控制   运输的那些方面。这保证了一些人的数据完整性   程度。以Sec-开头的标题名称不允许设置为   允许新的标题被铸造,保证不会来自   XMLHttpRequest的。

答案 5 :(得分:1)

我可以使用以下Gist解决此问题:
https://gist.github.com/killmenot/9976859

最初的想法来自这里:
https://gist.github.com/jfromaniello/4087861

我遇到了几个问题:

  1. Source Gist已过时,对我不起作用。例如,“request”lib API已更改。
  2. 我可以使用socket.io-client的“xmlhttprequest”库和 不要与socket.io-client安装在同一级别。
  3. 原始“socket.io-client”(0.9.16)使用“xmlhttprequest”(1.4.2) 支持“setDisableHeaderCheck”方法(但1.6.0确实如此)。所以,我做 一个分叉并使用它https://github.com/intspirit/socket.io-client/tree/0.9.16+20140408120400
  4. socket.io-client(1.0.0-pre)使用使用正确版本的xmlhttprequest的engine.io-client。我想将来我会使用1.0.0版本而不是我的fork,指定“xhr-polling”传输并模拟XMLHttpRequest作为原始要点。

答案 6 :(得分:-1)

我认为这个答案不够完整。

就像所有回答者所说的那样,由于安全完整性(浏览器无法判断您要添加的值是否是真实的cookie),您不能使用xhr.setRequestHeader('Cookie', "key=value");发送任何数据。

使用此特殊标头的预期方式是让客户端浏览器自动获取与您所请求的网站相关的所有Cookie,并将其放在“ Cookie”标头上,您无需执行其他任何操作,如果您的Cookie存在于浏览器中,则会发送它们。

...而且,如果您想知道,每次请求服务器的响应将您发送回Set-Cookie标头时,都应存储/更新浏览器中存储的所有cookie。因此,在请求中添加“ Set-Cookie”标头是没有意义的,因为它是仅保留用于响应的标头,并且不需要在您的请求中添加“ Cookie”标头,因为您的浏览器已经在执行此操作。