JQuery getJSON не отправляет файлы cookie

Я включаю JS в доменную область domain12

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

что script не загружается и на кнопке нажимает запрос JSONP на домен2

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

а затем отобразить данные на домене.

Итак, вот моя проблема: Запрос getJSON не отправляет файлы cookie в домен2. Самое странное, что он отправляет файлы cookie полдня, а другая - нет.: -)

Вот как выглядит запрос, когда он не работает:

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

Кто-нибудь видел такое поведение? Разрешима ли она?

Спасибо

Ответ 1

Если вы хотите использовать петиции AJAX в разных доменах/поддоменах, вам необходимо выполнить запросы на перекрестный поиск.

Литература:

Примеры:

Серверу необходимо отправить эти заголовки:

  • Access-Control-Allow-Origin: test1.floowie.com
  • Access-Control-Allow-Credentials: true//разрешать учетные данные cookie/сессии
  • Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS

Вы можете вернуть Access-Control-Allow-Origin глобально или установить специально зависящий от вашего ввода заголовок запроса Происхождение ($ _SERVER ['HTTP_ORIGIN]]. Также примените для Access-Control-Allow-Methods.

Вы должны выполнить ВАРИАНТЫ. Перед первым вызовом AJAX современные браузеры вызывают этот URL-адрес с помощью метода OPTIONS для извлечения вышеуказанных заголовков.

Хорошо, это первая часть, вторая - с 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", если хотите.

Ответ 2

Вы должны правильно внедрить запросы CORS с учетными данными для отправки и получения файлов cookie через Ajax. См. developer.mozilla.org, в частности в разделе "Запросы с учетными данными".

Прежде всего, вот простой запрос CORS Ajax с учетными данными, используя jQuery 1.5.1 +:

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

Обратите внимание на флаг withCredentials в xhrFields. Этот флаг сообщает браузеру отправлять файлы cookie с запросом на внешний домен, а не на источник происхождения. В вашем случае будут отправляться файлы cookie для www.domain2.com, и у вас будет доступ к ним на стороне сервера.

На стороне сервера вам нужно добавить определенные заголовки в ответ:

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 вашего ответа на это. В С# это так мы сделали:

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

После этого все файлы cookie, которые вы установите на стороне сервера, будут отправлены обратно с ответом, и браузер сможет правильно обработать их и вставить их в хранилище cookie браузера на www.domain2.com. И любые последующие запросы CORS, которые вы отправляете, отправят эти файлы cookie в запрос.

Если вы отправляете запрос, отличный от методов GET, POST или HEAD, вам нужно будет выполнить Запрошенные запросы (см. раздел "Предварительно запрошенные запросы" ):

В отличие от простых запросов (см. выше), запросы "предпусковые" сначала отправляют HTTP-запрос методом OPTIONS на ресурс в другом домене, чтобы определить, безопасно ли отправлять этот запрос. Запросы межсайтовых запросов предваряются таким образом, поскольку они могут иметь последствия для пользовательских данных. В частности, запрос предваряется, если:

  • Использует методы, отличные от GET, HEAD или POST. Кроме того, если POST используется для отправки данных запроса с помощью Content-Type, отличного от application/x-www-form-urlencoded, multipart/form-data или text/plain, например. если запрос POST отправляет XML-полезную нагрузку на сервер с помощью приложения /xml или text/xml, тогда запрос предваряется.

  • Он устанавливает пользовательские заголовки в запросе (например, запрос использует заголовок, например X-PINGOTHER)

Боковое примечание об IE8 и IE9: Вызов Ajax выше не будет работать в IE8 и 9. Я включил JS файл из MoonScript/jQuery-ajaxTransport-XDomainRequest на моей странице, и это автоматически разрешало запросы CORS работать в этих старых версиях IE. Но, к сожалению, объект XDomainRequest, созданный MS для IE8 и 9, не позволяет отправлять или получать файлы cookie. (см. это сообщение в блоге MSDN для получения дополнительной информации)

Ответ 3

У вас разные хосты. В первом примере хостом является "Host: www.floowie.com". Во втором - "Host: test1.floowie.com".

Я предполагаю, что файлы cookie изначально заданы "test1.floowie.com", и вы не указали, что они должны быть доступны ".floowie.com" (т.е. весь домен и все поддомены).

Можете ли вы опубликовать код, который устанавливает файлы cookie в первую очередь?

Если вы установите это исправление, оно должно хотя бы показать последовательное поведение. Тем не менее, IE, вероятно, все равно не будет передавать файлы cookie через субдомены. Это то, с чем я сейчас борюсь, так как я могу ответить на ваш вопрос.