Подтвердить что ты не робот

Почему браузер не устанавливает файлы cookie после возвращения запроса AJAX?

Я делаю запрос ajax, используя $.ajax. Ответ имеет набор заголовков Set-Cookie (я проверял это в инструментах Chrome dev). Однако браузер не устанавливает cookie после получения ответа! Когда я перехожу на другую страницу в своем домене, cookie не отправляется. (Примечание: я не выполняю межсайтовые запросы ajax, запрос находится в том же домене, что и документ.)

Что мне не хватает?

EDIT: Вот код для моего запроса ajax:

$.post('/user/login', JSON.stringify(data));

Вот запрос, как показано в инструментах Chrome dev:

Request URL:https://192.168.1.154:3000/user/login
Request Method:POST
Status Code:200 OK

Request Headers:
Accept:*/*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Content-Length:35
Content-Type:application/x-www-form-urlencoded; charset=UTF-8
DNT:1
Host:192.168.1.154:3000
Origin:https://192.168.1.154:3000
Referer:https://192.168.1.154:3000/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36
X-Requested-With:XMLHttpRequest

Form Data:
{"UserId":"blah","Password":"blah"}:

Ответ:

Response Headers:
Content-Length:15
Content-Type:application/json; charset=UTF-8
Date:Sun, 16 Mar 2014 03:25:24 GMT
Set-Cookie:SessionId=MTM5NDk0MDMyNHxEdi1CQkFFQ180SUFBUkFCRUFBQVRfLUNBQUVHYzNSeWFXNW5EQXNBQ1ZObGMzTnBiMjVKWkFaemRISnBibWNNTGdBc1ZFcDNlU3RKVFdKSGIzQlNXRkkwVjJGNFJ6TlRVSHA0U0ZJd01XRktjMDF1Y1c1b2FGWXJORzV4V1QwPXwWf1tz-2Fy_Y4I6fypCzkMJyYxhgM3LjVHGAlKyrilRg==; HttpOnly
4b9b3361

Ответ 1

ОК, поэтому я, наконец, понял проблему. Оказывается, установка параметра Path важна при отправке файлов cookie в запросе AJAX. Если вы установили Path=/, например:

Set-Cookie:SessionId=foo; Path=/; HttpOnly

... тогда браузер будет устанавливать cookie при переходе на другую страницу. Без настройки Path браузер использует путь по умолчанию. По-видимому, путь по умолчанию для cookie, заданный по запросу AJAX, отличается от пути по умолчанию, используемого при непосредственном перемещении по странице. Я использую Go/Martini, поэтому на стороне сервера я делаю это:

session.Options(session.Options{HttpOnly: true, Path:"/"})

Я бы предположил, что Python/Ruby/etc. имеют аналогичный механизм для установки Path.

См. также: проблема с cookie в PHP и AJAX

Ответ 2

Если вы используете новый API fetch, вы можете попробовать включить credentials:

fetch('/users', {
  credentials: 'same-origin'
})

То, что исправило это для меня.

В частности, используя polyfill: https://github.com/github/fetch#sending-cookies

Ответ 3

@atomkirk ответ не совсем применим ко мне, потому что

  • Я не использую API fetch
  • Я делал межсайтовые запросы (т.е. CORS)

Но ответ помог мне совершить эти прыжки:

fetch Запросы API CORS требуется {credentials:'include'} для отправки и получения файлов cookie

Для запросов CORS используйте значение "включить", чтобы разрешить отправкуучетные данные для других доменов:

fetch('https://example.com:1234/users', {   
            credentials: 'include' 
})

... Чтобы выбрать принятие файлов cookie с сервера, вы должны использовать параметр учетных данных.


{credentials:'include'} просто устанавливает xhr.withCredentials=true

Проверить fetch код

if (request.credentials === 'include') {
      xhr.withCredentials = true
 } 

Так что обычный Javascript/XHR.withCredentials является важной частью.


Если вы используете jQuery, вы можете установить withCredentials с помощью $.ajaxSetup(...)

$.ajaxSetup({
             crossDomain: true,
             xhrFields: {
                 withCredentials: true
             }
         });

Что касается запроса, когда xhr.withCredentials=true; заголовок Cookie отправляется

Прежде чем я изменил xhr.withCredentials=true

  • Я мог видеть имя и значение Set-Cookie в ответе, но вкладка "Приложение" Chrome в Инструментах разработчика показала мне имя и пустое значение
  • Последующие запросы не отправили a Cookie заголовок запроса.

После изменения xhr.withCredentials=true

  • Я мог видеть имя файла cookie и значение файла cookie на вкладке "Приложение" Chrome (значение, соответствующее Set-Cookie заголовок).
  • Последующие запросы сделали отправили заголовок запроса Cookie с тем же значением, поэтому мой сервер обработал меня как "аутентифицированный"

Что касается ответа: серверу могут понадобиться определенные заголовки Access-Control- *

Например, я настроил сервер для возврата этих заголовков:

  • Access-Control-Allow-Credentials: истинная
  • Access-Control-Allow-Origin: https://{ваши-происхождения}: {вашего порт}

Пока я не сделал это изменение на стороне сервера в заголовках ответов, Chrome зарегистрировал ошибки в консоли, например

Не удалось загрузить https://{saml-domain}/saml-authn: перенаправление с https://{saml-domain}/saml-redirect было заблокировано политикой CORS:

Значение заголовка 'Access-Control-Allow-Credentials' в ответе '', которое должно быть 'true', когда режим учетных данных запроса 'include'. Происхождение https://{your-domain}, следовательно, не допускается.

Режим учетных данных запросов, инициированных XMLHttpRequest, контролируется атрибутом withCredentials.

После внесения этого изменения заголовка Access- *, Chrome не регистрировал ошибки; браузер позволяет проверить аутентифицированные ответы для всех последующих запросов.