Html 为什么在使用 setRequestHeader 进行 xmlhttprequest 时无法设置 cookie 和 set-cookie 标头?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15198231/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 06:06:32  来源:igfitidea点击:

Why cookies and set-cookie headers can't be set while making xmlhttprequest using setRequestHeader?

javascripthtmlnode.jscookiesxmlhttprequest

提问by jsist

I was wondering why one cannot set cookieheaders using setRequestHeader. Is there any specific reason or just that they are added by browser itself, so these headers are disabled? Is there any security issue?

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

--Edit

- 编辑

I am working on node.js and used the xmlhttprequestmodule. Following is the test code:

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

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

Here I need to set cookie-header as node.js' xmlhttprequestdo not explicitly adds cookie-header(as browsers do). When trying to do so, xmlhttprequestgives error "Refused to set unsafe header".

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

Though I have found a patch and successfully able to send the cookie-header. But was wondering why it was disabled to set cookie-header? Where-ever I read, found that it is required for data-integrity and security, but what security can be breached in this case, is mentioned no where. I want to evaluate if, this data-integrity problem is valid for node.js application as well if I go with my patch.

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

采纳答案by Manish Singh

I am sure you would have gone through the working draftand found

我相信你会通过工作草案并发现

The above headers are controlled by the user agent to let it control those aspects of transport.

上述标头由用户代理控制,以使其控制传输的这些方面。

Firstly we need to understand, These are standards working as guidelines for interoperability of functions between different browsers. It's not mandated for the browser and hence browsers do have different level of adherence to this standard for different reasons.

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

Secondly, Technically speaking you can emulate a user agent , treat your program as the browser and can very well set those values as per mentioned standards.

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

Finally, the intent of disallowing overwriting of Headers or setting up headers for certain fields like Content-Length, Cookieethos the secure design approach. It is to discourage or at least try to discourage HTTP Request smuggling.

最后,禁止覆盖标题或为某些字段设置标题的意图,例如Content-Length, Cookieethos the secure design approach. 它是为了阻止或至少试图阻止 HTTP 请求走私

回答by robertklep

You can disable this behaviour:

您可以禁用此行为:

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

回答by Todd

As is well known, for browsers, cookies (among other properties) need to be carefully managed to prevent third parties from stealing user sessions (or other data). This is an issue with browsers, and the uncontrolled nature of visiting a website that runs arbitrary Javascript.

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

Of course this risk of arbitrary code execution is either a low or non-risk for node.js, as you only run a script which you wrote which may run other code you planned for.

当然,这种任意代码执行的风险对于 node.js 来说要么是低风险,要么是非风险,因为您只运行您编写的脚本,该脚本可能会运行您计划的其他代码。

If you have a look at the source code for driverdan's XMLHttpRequest.jsyou will find:

如果您查看 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"   ];

This answer your specific question of why the restriction particularly applies to this script used for node.js - the coder was following the spec (as closely as possible), despite that feeling it probably wasn't a required security precaution in node.js. Nevertheless this default security level is readily modified.

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

As robertklep pointed out, you can disable this default precaution by using the setDisableHeaderCheckmethod. And yes this final point does answer or contribute significantly toward an answer for your question because in your question you stated:

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

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

We have now found you didn't need that patch.

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

Good Luck!

祝你好运!

回答by user568109

Yes, it is required for data-integrity and security. To understand this, you have to understand the role of cookies in HTTP request methods.

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

Cookies are important in identifying the user, browser, connection etc and are stored at web browser. JavaScript allows you to manipulate cookies, but not all cookies on the browser. See HTTP cookies, these are only set by browser, so that user can't misuse it (via JavaScript).

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

On a supported browser, an HttpOnly session cookie will be used only when transmitting HTTP (or HTTPS) requests, thus restricting access from other, non-HTTP APIs (such as JavaScript).

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

When you send xmlhttprequest it reads HttpOnly cookies and sends to server via Cookieheader. Now if you do xhr.setRequestHeader('Cookie', "key=value");, you are trying to tamper with the cookies sent to server. setRequestHeaderwill add extra key=valuethat may compromise the integrity of the cookies sent.

当您发送 xmlhttprequest 时,它会读取 HttpOnly cookie 并通过Cookie标头发送到服务器。现在,如果你这样做了xhr.setRequestHeader('Cookie', "key=value");,你就是在试图篡改发送到服务器的 cookie。setRequestHeader将添加key=value可能会损害发送的 cookie 完整性的额外内容。

These are used by server to authenticate the user (session, email-account or any account). This essentially allows server to prevent misuse of cookies to get access into server.

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

回答by Bj?rn M?rtensson

the documentation mentions that this is done to protect data integrity. http://www.w3.org/TR/XMLHttpRequest/#the-setrequestheader%28%29-method

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

The above headers are controlled by the user agent to let it control those aspects of transport. This guarantees data integrity to some extent. Header names starting with Sec- are not allowed to be set to allow new headers to be minted that are guaranteed not to come from XMLHttpRequest.

上述标头由用户代理控制,以使其控制传输的这些方面。这在一定程度上保证了数据的完整性。不允许设置以 Sec- 开头的标头名称以允许创建新标头,这些标头保证不是来自 XMLHttpRequest。

回答by Alexey Kucherenko

I was able to resolve this problem using the following Gist:
https://gist.github.com/killmenot/9976859

我能够使用以下要点解决这个问题:https:
//gist.github.com/killmenot/9976859

The original idea is taken from here:
https://gist.github.com/jfromaniello/4087861

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

I faced with several problems:

我遇到了几个问题:

  1. Source Gist is outdated and doesn't work for me. For example "request" lib API was changed.
  2. I might work with socket.io-client's "xmlhttprequest" library and don't install on the same level with socket.io-client.
  3. Original "socket.io-client" (0.9.16) uses "xmlhttprequest" (1.4.2) that doesn't support "setDisableHeaderCheck" method (but 1.6.0 does). So, I make a fork and use it https://github.com/intspirit/socket.io-client/tree/0.9.16+20140408120400
  1. Source Gist 已经过时,对我不起作用。例如,“请求”库 API 已更改。
  2. 我可能会使用 socket.io-client 的“xmlhttprequest”库,并且不会与 socket.io-client 安装在同一级别。
  3. 原始“socket.io-client”(0.9.16)使用不支持“setDisableHeaderCheck”方法的“xmlhttprequest”(1.4.2)(但1.6.0支持)。所以,我做了一个叉子并使用它https://github.com/intspirit/socket.io-client/tree/0.9.16+20140408120400

socket.io-client (1.0.0-pre) uses engine.io-client that uses correct version of xmlhttprequest. I guess in the future I'll use 1.0.0 version instead of my fork, specify "xhr-polling" transport and mock XMLHttpRequest as the original gist does.

socket.io-client (1.0.0-pre) 使用 engine.io-client 使用正确版本的 xmlhttprequest。我想将来我会使用 1.0.0 版本而不是我的 fork,像原始要点一样指定“xhr-polling”传输和模拟 XMLHttpRequest。

回答by poet

I think this answers are not sufficiently complete.

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

Just as all of the asnwers says, you can't use xhr.setRequestHeader('Cookie', "key=value");to send any data because of security integrity (the browser can't tell if the value you are adding is a real cookie).

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

The expected way to work with this special header is to let the client browser automatlycally take all the cookies related to the site you are requesting and put them on the 'Cookie' header, you don't need to do anything else, if your cookies exist in your browser, they will be send.

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

...And if you are wondering, all the cookies stored in your browser are suposed to be stored/updated everytime a response from the server you are requesting sends you back a Set-Cookieheader. So it has no sense add a 'Set-Cookie' header in a request because it is a header reserved for responses only, and is not needed to add a 'Cookie' header in your requests because your browser is already doing it.

...如果您想知道,每次来自您请求的服务器的响应向您发送回Set-Cookie标头时,您浏览器中存储的所有 cookie 都应该被存储/更新。因此,在请求中添加“Set-Cookie”标头是没有意义的,因为它是仅为响应保留的标头,并且不需要在您的请求中添加“Cookie”标头,因为您的浏览器已经在这样做了。