javascript jQuery getJSON 不发送 cookie

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6930650/
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-10-25 22:22:48  来源:igfitidea点击:

jQuery getJSON doesnt send cookies

javascriptjqueryajaxcookiescross-domain

提问by BlueZero

i am including JS on domain1 form domain2

我在 domain1 表单 domain2 上包含 JS

<script type="text/javascript" src="http://www.domain2.com/script.js"></script>

that script doesn onload and on button click a JSONP request to domain2

该脚本不会加载并在按钮上单击对 domain2 的 JSONP 请求

$.getJSON( 'http://www.domain2.com/process?callback=?',
    function(data){
        if ( data ) processData( data );
    }
);

and then displaying the data on domain1.

然后在 domain1 上显示数据。

So here is my problem: The getJSON request doesnt send cookies to the domain2. The weirdest thing is that it does send the cookies half a day and the other half not. :-)

所以这是我的问题:getJSON 请求不会将 cookie 发送到 domain2。最奇怪的是,它确实发送了半天的 cookie 而另一半则没有。:-)

This is how the request looks like when it doesnt work:

这是请求不起作用时的样子:

Request details
GET /ajax/embed-user-library?detail=98&callback=jsonp1312398534998 HTTP/1.1 
User-Agent: Opera/9.80 (Windows NT 6.1; U; en) Presto/2.9.168 Version/11.50
Host: www.floowie.com
Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1
Accept-Language: en,sk-SK;q=0.9,sk;q=0.8
Accept-Encoding: gzip, deflate
Referer: http://www.sokker.cz/en/test2
Connection: Keep-Alive

Response details
HTTP/1.1 200 OK 
Date: Wed, 03 Aug 2011 19:06:51 GMT
Server: Apache/2.2.16 (Debian)
X-Powered-By: PHP/5.3.5-0.dotdeb.1
Set-Cookie: SESSID=64292b70dc28d7c6c9f13f70070353d8; path=/; domain=.floowie.com
Expires: Mon, 26 Jul 1997 05:00:00 GMT
Cache-Control: no-cache, must-revalidate
Pragma: no-cache
Content-Length: 34
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: application/json

And this when it works(nothing changed in the scripts):

当它工作时(脚本中没有任何变化):

Request details
GET /ajax/embed-user-library?detail=99&test=1&callback=jsonp1312398534999 HTTP/1.1 
User-Agent: Opera/9.80 (Windows NT 6.1; U; en) Presto/2.9.168 Version/11.50
Host: test1.floowie.com
Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1
Accept-Language: en,sk-SK;q=0.9,sk;q=0.8
Accept-Encoding: gzip, deflate
Referer: http://www.sokker.cz/en/test2
Cookie: __utma=254918925.1489796832.1301725317.1312260335.1312298033.44; __utmz=254918925.1312298033.44.11.utmcsr=sokker.cz|utmccn=(referral)|utmcmd=referral|utmcct=/en/test2; lang=en; FLWSESSID=ddd1bc696f83f5a70b5f0f3ae30b4691; __utma=121955676.1030804516.1282595153.1312390656.1312397285.194; __utmb=121955676.8.10.1312397285; __utmc=121955676; __utmz=121955676.1312397285.194.21.utmcsr=floowie.crmserver.cz|utmccn=(referral)|utmcmd=referral|utmcct=/index.php
Connection: Keep-Alive

Response details
HTTP/1.1 200 OK 
Date: Wed, 03 Aug 2011 19:07:45 GMT
Server: Apache/2.2.16 (Debian)
X-Powered-By: PHP/5.3.5-0.dotdeb.1
Expires: Mon, 26 Jul 1997 05:00:00 GMT
Cache-Control: no-cache, must-revalidate
Pragma: no-cache
Content-Length: 20
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: application/json

Did someone see such a behaviour? Is it solvable?

有人看到过这种行为吗?可以解决吗?

Thank you

谢谢

回答by Mar?al Juan

If you want to use AJAX petitions over different domains/subdomains you have to implement Cross Origin Requests.

如果你想在不同的域/子域上使用 AJAX 请求,你必须实现跨域请求。

References:

参考:

Examples:

例子:

Your server needs to send this headers:

您的服务器需要发送此标头:

  • Access-Control-Allow-Origin: test1.floowie.com
  • Access-Control-Allow-Credentials: true // allow cookie/session credentials
  • Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
  • 访问控制允许来源:test1.floowie.com
  • Access-Control-Allow-Credentials: true // 允许 cookie/会话凭据
  • 访问控制允许方法:GET、POST、PUT、DELETE、OPTIONS

You can return the Access-Control-Allow-Originglobally or set specifically dependent of your input Origin($_SERVER['HTTP_ORIGIN']) request header. Also apply for Access-Control-Allow-Methods.

您可以全局返回Access-Control-Allow-Origin或根据您的输入Origin($_SERVER['HTTP_ORIGIN']) 请求标头专门设置。也申请Access-Control-Allow-Methods

You mustimplement the OPTIONSpetition. Before the first AJAX call, modern browsers call that URL with an OPTIONS method to retrieve the above headers.

必须执行OPTIONS请愿书。在第一次 AJAX 调用之前,现代浏览器使用 OPTIONS 方法调用该 URL 以检索上述标头。

Ok this is the first part, the second is with jQuery. Read very carefully this page: http://api.jquery.com/jQuery.ajax/

好的,这是第一部分,第二部分是 jQuery。仔细阅读此页面:http: //api.jquery.com/jQuery.ajax/

You will need to add some options to every AJAX call, you can do it globally:

您需要为每个 AJAX 调用添加一些选项,您可以全局执行:

$(document).ajaxSend(function (event, xhr, settings) {
    settings.xhrFields = {
        withCredentials: true
    };
});

Or specific:

或者具体:

$.ajax({
    url: a_cross_domain_url,
    xhrFields: {
        withCredentials: true
    }
});

This issue made ??me lose manyhours... hope it helps.

这个问题让我失去了很多时间......希望它有所帮助。

Note that you won't need to set your cookie domain as ".floowie.com" if you want.

请注意,如果需要,您无需将 cookie 域设置为“.floowie.com”。

回答by John Washam

You must properly implement CORS requests with credentials to send and receive cookies via Ajax. See developer.mozilla.org, specifically under the section titled "Requests with credentials."

您必须使用凭据正确实施 CORS 请求,才能通过 Ajax 发送和接收 cookie。请参阅developer.mozilla.org,特别是在标题为“具有凭据的请求”部分下。

First off, here is a simple CORS Ajax request with credentials, using jQuery 1.5.1+:

首先,这是一个使用 jQuery 1.5.1+ 的带有凭据的简单 CORS Ajax 请求:

$.ajax({
    url: "http://www.domain2.com/process",
    xhrFields: {
        withCredentials: true
    }
}).done(function (data) { console.log(data); });

Note the withCredentialsflag in the xhrFields. This flag tells the browser to send cookies with the request for the externaldomain, not the origindomain. In your case, cookies for www.domain2.comwill be sent, and you will have access to them server-side.

请注意withCredentialsxhrFields 中的标志。这个标志告诉浏览器发送带有外部域请求的 cookie ,而不是域。在您的情况下,将发送www.domain2.com 的cookie ,您将可以在服务器端访问它们。

On the server-side, you need to add certain headers to the response:

在服务器端,您需要向响应添加某些标头:

Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: www.domain1.com

Important:requests with credentials cannot set the Access-Control-Allow-Originheader to global (Access-Control-Allow-Origin: *). It must specify domains (Access-Control-Allow-Origin: www.domain1.com).

重要提示:具有凭据的请求不能将Access-Control-Allow-Origin标头设置为全局 ( Access-Control-Allow-Origin: *)。它必须指定域 ( Access-Control-Allow-Origin: www.domain1.com)。

It's obviously better if you specify a domain for the Access-Control-Allow-Originheader. But if you don't know or care where the CORS request is coming from, you could use the Originheader from the request and simply set the Access-Control-Allow-Originheader of your response to that. In C#, this is how we did this:

如果为Access-Control-Allow-Origin标头指定域,显然会更好。但是,如果您不知道或不关心 CORS 请求的来源,您可以使用Origin请求中的标头,并将响应的Access-Control-Allow-Origin标头设置为该标头。在 C# 中,我们是这样做的:

this.Response.AddHeader("Access-Control-Allow-Origin", this.Request.Headers["Origin"]);

After doing all of this, cookies that you set server-side will be sent back with the response, and the browser will be able to properly handle them and insert them into the browser's cookie store for www.domain2.com. And any subsequent CORS requests you send will send these cookies in the request as well.

完成所有这些之后,您在服务器端设置的 cookie 将与响应一起发回,浏览器将能够正确处理它们并将它们插入浏览器的www.domain2.comcookie 存储中。您发送的任何后续 CORS 请求也会在请求中发送这些 cookie。

If you are sending a request other than with the GET, POST, or HEAD methods, you will need to implement Preflighted requests(see under section titled "Preflighted requests"):

如果您发送的请求不是使用 GET、POST 或 HEAD 方法,您将需要实现预检请求(参见标题为“预检请求”的部分):

Unlike simple requests (discussed above), "preflighted" requests first send an HTTP request by the OPTIONS method to the resource on the other domain, in order to determine whether the actual request is safe to send. Cross-site requests are preflighted like this since they may have implications to user data. In particular, a request is preflighted if:

  • It uses methods other than GET, HEAD or POST. Also, if POST is used to send request data with a Content-Type other than application/x-www-form-urlencoded, multipart/form-data, or text/plain, e.g. if the POST request sends an XML payload to the server using application/xml or text/xml, then the request is preflighted.

  • It sets custom headers in the request (e.g. the request uses a header such as X-PINGOTHER)

与简单请求(上面讨论过)不同,“预检”请求首先通过 OPTIONS 方法向其他域上的资源发送 HTTP 请求,以确定实际请求是否可以安全发送。跨站点请求是这样预检的,因为它们可能会对用户数据产生影响。特别是,在以下情况下对请求进行预检:

  • 它使用 GET、HEAD 或 POST 以外的方法。此外,如果 POST 用于发送内容类型不是 application/x-www-form-urlencoded、multipart/form-data 或 text/plain 的请求数据,例如,如果 POST 请求向服务器发送 XML 有效负载使用 application/xml 或 text/xml,然后预检请求。

  • 它在请求中设置自定义标头(例如,请求使用 X-PINGOTHER 等标头)

Side-note about IE8 and IE9:The Ajax call above will fail in IE8 and 9. I included the JS file from MoonScript/jQuery-ajaxTransport-XDomainRequeston my page, and this automagically allowed CORS requests to work in those old IE versions. But sadly, the XDomainRequest object that MS created for IE8 and 9 does not allow cookies to be sent or received. (see this MSDN blog postfor more information)

关于 IE8 和 IE9 的旁注:上面的 Ajax 调用将在 IE8 和 9 中失败。我在我的页面上包含了来自MoonScript/jQuery-ajaxTransport-XDomainRequest的 JS 文件,这自动允许 CORS 请求在那些旧的 IE 版本中工作。但遗憾的是,微软为 IE8 和 9 创建的 XDomainRequest 对象不允许发送或接收 cookie。(有关更多信息,请参阅此 MSDN 博客文章

回答by stco

You have different hosts. In the first example the host is "Host: www.floowie.com". In the second it is "Host: test1.floowie.com".

你有不同的主机。在第一个示例中,主机是“主机:www.floowie.com”。第二个是“主机:test1.floowie.com”。

I'm guessing that the cookies are originally set by 'test1.floowie.com' and you haven't specified that they should be available to '.floowie.com' (i.e. the whole domain and all subdomains).

我猜这些 cookie 最初是由“test1.floowie.com”设置的,而您没有指定它们应该可用于“.floowie.com”(即整个域和所有子域)。

Can you post the code that sets the cookies in the first place?

您可以发布首先设置 cookie 的代码吗?

If you get this fixed, it should at least show consistent behaviour. However, IE will probably still not pass cookies across subdomains. That's what I'm wrestling with at the moment, which is how I can across your question.

如果你解决了这个问题,它至少应该表现出一致的行为。但是,IE 可能仍然不会跨子域传递 cookie。这就是我目前正在努力解决的问题,这就是我如何解决你的问题。