jQuery getJSON不发送cookie

时间:2011-08-03 17:33:38

标签: javascript jquery ajax cookies cross-domain

我在domain1表单domain2上包含JS

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

该脚本没有onload和on按钮单击对domain2的JSONP请求

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

然后在domain1上显示数据。

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

这是请求无效时的样子:

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

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

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

有人看到这样的行为吗? 它可以解决吗?

谢谢

3 个答案:

答案 0 :(得分:30)

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

参考文献:

示例:

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

  • Access-Control-Allow-Origin :test1.floowie.com
  • Access-Control-Allow-Credentials :true //允许Cookie /会话凭据
  • 访问控制允许方法:GET,POST,PUT,DELETE,OPTIONS

您可以全局返回 Access-Control-Allow-Origin ,也可以根据输入 Origin ($ _SERVER ['HTTP_ORIGIN'])请求标头进行设置。同时申请访问控制 - 允许 - 方法

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

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

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

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

或具体:

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

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

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

答案 1 :(得分:1)

您必须正确实施具有凭据的CORS请求,以通过Ajax发送和接收cookie。请参阅developer.mozilla.org,特别是标题为&#34;带凭据的请求部分。&#34;

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

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

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

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

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

重要:带凭据的请求无法将 Access-Control-Allow-Origin 标头设置为全局(Access-Control-Allow-Origin: *)。它必须指定域(Access-Control-Allow-Origin: www.domain1.com)。

如果为 Access-Control-Allow-Origin 标头指定域,情况会更好。但是,如果您不知道或不关心CORS请求的来源,您可以使用请求中的Origin标头,只需设置 Access-Control-Allow-Origin 你对此的回应标题。在C#中,我们就是这样做的:

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

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

如果您发送的请求不是使用GET,POST或HEAD方法,则需要实施Preflighted requests(请参阅标题为&#34; Preflighted requests&#34;)

  

与简单请求(如上所述)不同,&#34;预先发布&#34;请求首先通过OPTIONS方法向另一个域上的资源发送HTTP请求,以确定实际请求是否可以安全发送。跨站点请求是这样预检的,因为它们可能对用户数据有影响。特别是,如果出现以下情况,请求会被预检:

     
      
  • 它使用GET,HEAD或POST以外的方法。此外,如果使用POST来发送具有除application / x-www-form-urlencoded,multipart / form-data或text / plain之外的Content-Type的请求数据,例如,如果POST请求使用application / xml或text / xml向服务器发送XML有效负载,则该请求将被预检。

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

  •   

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

答案 2 :(得分:-1)

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

我猜测这些cookie最初是由'test1.floowie.com'设置的,而你没有指明它们应该可用于'.floowie.com'(即整个域和所有子域名)。< / p>

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

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