(注意:这是我的问题的后续jQuery.getJSON 能否将域的 cookie 放入其发出的请求的标头中? 并涵盖 在 AJAX 请求中设置 cookie?)
我被告知无法设置 cookie由非当前域子域的其他域使用 $.cookie(..., ..., {domain: ...})
读取。但在对我最后一个问题的回复的评论中,@zanlok 说“但是,服务器的回复肯定可以设置 cookie”,并且获得了两票赞成。
所以我想我应该尝试使用一项服务,该服务是为了设置 cookie 的明确目的而创建的,名为 Freebase 的“触摸”API。调用看起来像:
$.getJSON("http://api.sandbox-freebase.com/api/service/touch",
{}, // URL parameters
afterCookieIsSetCallback); // Callback function
在 FireBug 中查看响应头,它是这样的:
Date Wed, 24 Nov 2010 03:35:28 GMT
Server Apache
X-Metaweb-Cost [...]
Etag [...]
Expires Wed, 24 Nov 2010 03:35:29 GMT
Cache-Control no-store
Vary Accept-Encoding
Content-Encoding gzip
Set-Cookie mwLastWriteTime=1290569730|10325_9202a8c04000641f80000000199eff96|sandbox; expires=Thu, 25-Nov-2010 03:35:28 GMT; Path=/
Last-Modified Wed, 24 Nov 2010 03:35:28 GMT
Content-Length 134
Content-Type text/plain; charset=utf-8
X-Cache MISS from cache01.sandbox.sjc1.metaweb.com
Connection keep-alive
X-Metaweb-TID cache;cache01.sandbox.sjc1:8101;2010-11-24T03:35:28Z;0001
所以那里肯定有一个 Set-Cookie,并且脚本运行响应处理程序。然而,此脚本向 .sandbox-freebase.com
发出的后续 JSON 请求的请求标头中不存在 cookie。
(相比之下,只需在地址栏中输入 touch api URL 并以这种方式加载它,就会为将来的请求设置 cookie。这甚至适用于其他选项卡。)
这似乎与之前的“预期行为”有偏差,因为MetaWeb 大约“2007-2009”发布了一个工具包,它似乎认为这种方法可行:
http://www.google.com/codesearch /p?hl=en#v099O4eZ5cA/trunk/src/freebase/api.js&q=touch%20package:http://mjt%5C.googlecode%5C.com&l=340
不太了解我想知道这是否是 Firefox 最近采用的一项更改,然后 WebKit 也效仿了。也许这里提到的:
http://trac.webkit。 org/browser/trunk/WebCore/xml/XMLHttpRequest.cpp#L856
那么有关于这个特定问题的规范文档吗?
(Note: This is a follow up to my question Can jQuery.getJSON put a domain's cookies in the header of the request it makes? and covers the XSS case of Setting a cookie in an AJAX request?)
I've been told I'm unable to set cookies to be read by other domains that are not subdomains of the current domain using $.cookie(..., ..., {domain: ...})
. But in a comment on a response to my last question, @zanlok said "The server's reply, however, can definitely set a cookie" and it got two upvotes.
So I thought I'd try using a service which was created for the explicit purpose of setting cookies called Freebase's "touch" API. The call looks like:
$.getJSON("http://api.sandbox-freebase.com/api/service/touch",
{}, // URL parameters
afterCookieIsSetCallback); // Callback function
Looking in FireBug at the response header it's like this:
Date Wed, 24 Nov 2010 03:35:28 GMT
Server Apache
X-Metaweb-Cost [...]
Etag [...]
Expires Wed, 24 Nov 2010 03:35:29 GMT
Cache-Control no-store
Vary Accept-Encoding
Content-Encoding gzip
Set-Cookie mwLastWriteTime=1290569730|10325_9202a8c04000641f80000000199eff96|sandbox; expires=Thu, 25-Nov-2010 03:35:28 GMT; Path=/
Last-Modified Wed, 24 Nov 2010 03:35:28 GMT
Content-Length 134
Content-Type text/plain; charset=utf-8
X-Cache MISS from cache01.sandbox.sjc1.metaweb.com
Connection keep-alive
X-Metaweb-TID cache;cache01.sandbox.sjc1:8101;2010-11-24T03:35:28Z;0001
So there's definitely a Set-Cookie in there, and the script runs the response handler. Yet the cookie is not present in the request headers for later JSON requests this script makes to .sandbox-freebase.com
.
(By contrast, simply typing the touch api URL into the address bar and loading it that way does set the cookie for future requests. That applies even in other tabs.)
This seems to be a deviation from a prior "expected behavior", because there was a toolkit published by MetaWeb circa "2007-2009" which seemed to think such an approach could work:
http://www.google.com/codesearch/p?hl=en#v099O4eZ5cA/trunk/src/freebase/api.js&q=touch%20package:http://mjt%5C.googlecode%5C.com&l=340
Without knowing much about it, I'm wondering if it was a recent change that Firefox adopted and then WebKit followed suit. Perhaps the one mentioned here:
http://trac.webkit.org/browser/trunk/WebCore/xml/XMLHttpRequest.cpp#L856
So is there any canonical documentation on this particular issue?
发布评论
评论(2)
您正在进行的 AJAX 调用正在向顶级 url(地址栏中的 url)域之外的域发出请求。这导致它成为第 3 方 cookie,默认情况下 Internet Explorer 不会保留第 3 方 cookie。这意味着 cookie 将在第一个请求时返回到 Set-Cookie 标头中,但您向该服务器发出的后续请求将不会在请求中发送该 cookie。
就像你说的,如果你直接在浏览器中访问该网址,它就可以工作。这是因为在本例中它是第一方 cookie。
为了让 IE 接受第 3 方 cookie,在其响应中发送
SET-COOKIE
标头的服务器还必须设置 P3P 策略标头。这是一个例子,当您导航到 CNN 时,您会注意到它发出的请求之一是 b.scorecardresearch.com 域名,scorecardresearch 正在删除一个跟踪 cookie,但该 cookie 被视为第 3 方 cookie。因此,为了使其工作,他们还必须包含一个
p3p
标头,请参阅下面的标头:如果您要复制此标头并将其添加到响应中,您会注意到 cookie 开始工作,
最好为您的业务制作一个特定的 P3P 标头,但以上内容应该适用于测试目的。
The AJAX call you are making, is making a request to a domain outside of the domain of the top level url(the url in the address bar). This results in it being a 3rd party cookie, by default Internet explorer won't persist a 3rd party cookie. Meaning that the cookie will come back in the Set-Cookie header on the first request, but subsequent requests that you make to that server will not have that cookie sent in the request.
Like you said, if you go directly to the url in your browser it works. This is because in this case it's a first party cookie.
In order for IE to accept 3rd party cookie's the server that is sending the
SET-COOKIE
header on it's response, must also have a P3P Policy Header set.Here is an example, when you navigate to CNN, you will notice one of the requests it makes is to a domain name of b.scorecardresearch.com, scorecardresearch is dropping a tracking cookie, but this cookie is considered a 3rd party cookie. So in order to make it work they had to also in include a
p3p
header, see headers below:If you were to copy this header and add it to the response, you would notice that the cookie's start working,
It's best that you craft a P3P header specific for your business, but the above should work for testing purposes.
如果我没理解错的话,您可能想知道为什么服务器仅在第一个请求时发送
Set-Cookie
。如果这是真的,那么这是设计使然 - 请看这里:Set-Cookie
就像一个 setter - 服务器将其发送给浏览器以在本地缓存。它可以每次都发送,但没有必要这样做,因此只有需要更改本地存储的值时才会再次发送。另一方面,浏览器每次都会发送
Cookie
标头,其中包含服务器上次发出的Set-Cookie
设置的内容。If I correctly understand you, you are wondering why the server sends
Set-Cookie
only on the first request. If that is true, then it's by design - take a look here:Set-Cookie
is like a setter - the server sends it for the browser to cache it locally. It can send every time, but there is no need to do that, so it will send it again only if it needs to change the value stored locally.Browser, on the other hand, will send
Cookie
header every time with the contents set by the last issuedSet-Cookie
from the server.