Почему метод jaquery .ajax () не отправляет мой сеансовый cookie? - PullRequest
317 голосов
/ 20 мая 2010

После входа на сайт через $.ajax() я пытаюсь отправить второй запрос $.ajax() на этот сайт - но когда я проверяю заголовки, отправленные с помощью FireBug, в запрос не включается файл cookie сеанса.

Что я делаю не так?

Ответы [ 10 ]

364 голосов
/ 25 августа 2011

Я работаю в междоменном сценарии. При входе в систему удаленный сервер возвращает заголовок Set-Cookie вместе с Access-Control-Allow-Credentials, установленным в значение true.

Следующий файл ajax для удаленного сервера должен использовать этот файл cookie.

CORS Access-Control-Allow-Credentials предназначен для ведения междоменной регистрации. Проверьте https://developer.mozilla.org/En/HTTP_access_control для примеров.

Для меня это похоже на ошибку в JQuery (или, по крайней мере, в следующей версии).

UPDATE:

  1. Файлы cookie не устанавливаются автоматически из ответа AJAX (цитата: http://aleembawany.com/2006/11/14/anatomy-of-a-well-designed-ajax-login-experience/)

    Почему?

  2. Вы не можете получить значение cookie из ответа, чтобы установить его вручную (http://www.w3.org/TR/XMLHttpRequest/#dom-xmlhttprequest-getresponseheader)

    Я в замешательстве ..

    Должен существовать способ попросить jquery.ajax() установить параметр XMLHttpRequest.withCredentials = "true".

ОТВЕТ: Вы должны использовать xhrFields параметр http://api.jquery.com/jQuery.ajax/

Пример в документации:

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

Также важно, чтобы сервер правильно отвечал на этот запрос. Копирование здесь замечательных комментариев от @ Frédéric и @Pebbl:

Important note: when responding to a credentialed request, server must specify a domain, and cannot use wild carding. The above example would fail if the header was wildcarded as: Access-Control-Allow-Origin: *

Так что, когда запрос:

Origin: http://foo.example
Cookie: pageAccess=2

Сервер должен ответить:

Access-Control-Allow-Origin: http://foo.example
Access-Control-Allow-Credentials: true

[payload]

В противном случае полезная нагрузка не будет возвращена сценарию. Смотри: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials

203 голосов
/ 24 марта 2011

AJAX-вызовы отправляют Cookies только в том случае, если URL-адрес, по которому вы звоните, находится в том же домене, что и ваш скрипт вызова.

Это может быть междоменная проблема.

Возможно, вы пытались вызвать URL-адрес с www.domain-a.com, когда ваш скрипт вызова был на www.domain-b.com (Другими словами: вы сделали междоменный вызов, и в этом случае браузер не будет отправлять файлы cookie для защиты вашей конфиденциальности) .

В этом случае ваши варианты:

  • Напишите небольшой прокси, который находится на домене-b и перенаправляет ваши запросы на домен-a. Ваш браузер позволит вам вызывать прокси-сервер, потому что он находится на том же сервере, что и вызывающий скрипт.
    Затем вы можете настроить этот прокси-сервер так, чтобы он принимал имя и значение параметра cookie, которые он может отправлять в domain-a. Но для того, чтобы это работало, вам нужно знать имя куки-файла и значение вашего сервера в домене-a, требующем аутентификации.
  • Если вы выбираете объекты JSON, попробуйте вместо этого использовать запрос JSONP . JQuery поддерживает это. Но вам нужно изменить свой сервис в домене-a, чтобы он возвращал действительные ответы JSONP.

Рад, что это хоть немного помогло.

46 голосов
/ 14 мая 2014

Использование

xhrFields: { withCredentials:true }

как часть моего вызова jQuery ajax была только частью решения. Мне также нужно было вернуть заголовки в ответе ОПЦИИ от моего ресурса:

Access-Control-Allow-Origin : http://www.wombling.com
Access-Control-Allow-Credentials : true

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

Я подумал, что стоит явно указать требование только для одного источника, поскольку стандарт W3C допускает разделенный пробелами список, но Chrome нет! http://www.w3.org/TR/cors/#access-control-allow-origin-response-header NB Бит "на практике".

39 голосов
/ 19 марта 2015

Поместите это в вашу функцию инициализации:

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

Это будет работать.

11 голосов
/ 21 мая 2014

На этот вопрос уже есть много хороших ответов, но я подумал, что было бы полезно уточнить случай, когда вы ожидаете, что сеансовый cookie будет отправлен, потому что домен cookie совпадает, но он не отправляется, потому что AJAX-запрос делается на другой поддомен. В этом случае у меня есть файл cookie, назначенный домену *. Mydomain.com , и я хочу, чтобы он был включен в запрос AJAX для different.mydomain.com". По умолчанию файл cookie не отправляется. Вам не нужно отключать HTTPONLY в файле cookie сеанса, чтобы решить эту проблему. Вам нужно только сделать то, что предложено вомблингом (https://stackoverflow.com/a/23660618/545223), и выполнить следующее.

1) Добавьте следующее в ваш запрос ajax.

xhrFields: { withCredentials:true }

2) Добавьте следующее в заголовки ответа для ресурсов в другом поддомене.

Access-Control-Allow-Origin : http://original.mydomain.com
Access-Control-Allow-Credentials : true
6 голосов
/ 23 февраля 2018

Попробовав другие решения и все еще не заставив их работать, я выяснил, в чем проблема в моем случае. Я изменил contentType с «application / json» на «text / plain».

$.ajax(fullUrl, {
    type: "GET",
    contentType: "text/plain",
    xhrFields: {
         withCredentials: true
    },
    crossDomain: true
});
4 голосов
/ 12 октября 2013

У меня возникла та же проблема, и при некоторых проверках мой сценарий просто не получал cookie-файл sessionid.

Я выяснил, просмотрев значение cookie cookie сеанса в браузере, что мой фреймворк (Django) передавал cookie cookie сеанса с HttpOnly по умолчанию. Это означало, что скрипты не имели доступа к значению sessionid и поэтому не передавали его вместе с запросами. Довольно смешно, что HttpOnly будет значением по умолчанию, когда так много вещей используют Ajax, что потребует ограничения доступа.

Чтобы исправить это, я изменил настройку (SESSION_COOKIE_HTTPONLY = False), но в других случаях это может быть флаг "HttpOnly" на пути к cookie

1 голос
/ 11 июля 2015

Если вы разрабатываете на localhost или порте на localhost, таком как localhost:8080, в дополнение к шагам, описанным в ответах выше, вам также необходимо убедиться, что вы не передаете значение домена в Set Заголовок cookie.
Вы не можете установить домен на localhost в заголовке Set-Cookie - это неправильно - просто опустите домен.

См. Файлы cookie на локальном хосте с явным доменом и Почему asp.net не создает файлы cookie на локальном хосте?

0 голосов
/ 15 ноября 2018

Только мои 2 цента при установке проблемы с файлом cookie PHPSESSID при работе на локальном хосте и в среде разработчика. Я делаю AJAX-вызов к моей конечной точке REST API на locahost. Скажите, что его адрес mysite.localhost/api/member/login/ (virtal host в моей среде разработки).

  • Когда я делаю этот запрос на Почтальон , все идет хорошо, и PHPSESSID устанавливается с ответом.

  • Когда я запрашиваю эту конечную точку через AJAX со страницы прокси-сервера Browsersync (например, с 122.133.1.110:3000/test/api/login.php в адресной строке моего браузера, вижу, что домен отличается от mysite.localhost) PHPSESSID не появляется среди файлов cookie.

  • Когда я делаю этот запрос прямо со страницы в том же домене (т.е. mysite.localhost/test/api/login.php), PHPSESSID устанавливается просто отлично.

Итак, это проблема с файлами cookie для запросов на отправку из разных источников, как упоминалось в @flu ответ выше

0 голосов
/ 05 августа 2014

Возможно, не 100% ответили на вопрос, но я наткнулся на эту ветку в надежде решить проблему сеанса, когда ajax публикует загрузку файла из менеджера ресурсов редактора innovastudio. В конце концов решение было простым: у них есть флэш-загрузчик. Отключение этого (настройка

var flashUpload = false;   

в asset.php), и огни снова начали мигать.

Так как эти проблемы могут быть очень трудными для отладки, я обнаружил, что размещение чего-то вроде следующего в обработчике загрузки установит вас (ну, в данном случае, меня) на правильный путь:

$sn=session_name();
error_log("session_name: $sn ");

if(isset($_GET[$sn])) error_log("session as GET param");
if(isset($_POST[$sn])) error_log("session as POST param");
if(isset($_COOKIE[$sn])) error_log("session as Cookie");
if(isset($PHPSESSID)) error_log("session as Global");

Погружение в журнал, и я быстро обнаружил пропущенный сеанс, на который не было отправлено печенье.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...