Почему метод jaquery.ajax() не отправляет мой сеансовый cookie?
После входа через $.ajax()
на сайт, я пытаюсь отправить второй $.ajax()
запрос к этому сайту - но когда я проверяю заголовки, отправленные с помощью FireBug, в запрос не включается сессионный cookie.
Что я делаю неправильно?
13 ответов
Вызовы AJAX отправляют Cookies только в том случае, если URL-адрес, по которому вы звоните, находится в том же домене, что и ваш скрипт вызова.
Это может быть междоменной проблемой.
Может быть, вы пытались позвонить с URL www.domain-a.com
пока ваш вызывающий скрипт был включен www.domain-b.com
(Другими словами: вы совершили междоменный вызов, и в этом случае браузер не будет отправлять файлы cookie для защиты вашей конфиденциальности).
В этом случае ваши варианты:
- Напишите небольшой прокси, который находится на домене-b и перенаправляет ваши запросы на домен-a. Ваш браузер позволит вам вызывать прокси, потому что он находится на том же сервере, что и вызывающий скрипт.
Затем вы можете настроить этот прокси-сервер так, чтобы он принимал имя файла cookie и параметр значения, которые он может отправлять в домен a. Но для того, чтобы это работало, вам нужно знать имя куки-файла и значение вашего сервера в домене-a, требующем аутентификации. - Если вы выбираете объекты JSON, попробуйте вместо этого использовать запрос JSONP. JQuery поддерживает это. Но вам нужно изменить свой сервис в домене-a, чтобы он возвращал действительные ответы JSONP.
Рад, что это помогло хоть немного.
Я работаю в междоменном сценарии. При входе в систему удаленный сервер возвращает заголовок Set-Cookie вместе с Access-Control-Allow-Credentials
установите в true.
Следующий ajax-вызов на удаленный сервер должен использовать этот файл cookie.
CORS-х Access-Control-Allow-Credentials
есть ли возможность междоменной регистрации. Проверьте https://developer.mozilla.org/En/HTTP_access_control для примеров.
Для меня это похоже на ошибку в JQuery (или, по крайней мере, в следующей версии).
ОБНОВИТЬ:
Файлы cookie не устанавливаются автоматически из ответа AJAX (ссылка: http://aleembawany.com/2006/11/14/anatomy-of-a-well-designed-ajax-login-experience/)
Зачем?
Вы не можете получить значение куки из ответа, чтобы установить его вручную ( http://www.w3.org/TR/XMLHttpRequest/)
Я не совсем понимаю..
Должен существовать способ спросить
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
С помощью
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 Бит "на практике".
Поместите это в вашу функцию инициализации:
$.ajaxSetup({
xhrFields: {
withCredentials: true
}
});
Это будет работать.
На этот вопрос уже есть много хороших ответов, но я подумал, что было бы полезно уточнить случай, когда вы ожидаете, что cookie-файл сеанса будет отправлен, потому что домен cookie-файлов совпадает, но он не отправляется, поскольку запрос AJAX делается на другой поддомен. В этом случае у меня есть файл cookie, который назначен домену *.mydomain.com, и я хочу, чтобы он был включен в запрос AJAX для другого.mydomain.com". По умолчанию файл cookie не отправляется. Вам не нужно отключать HTTPONLY в файле cookie сеанса для решения этой проблемы. Вам нужно только сделать то, что предложено вомблинг ( /questions/41995244/pochemu-metod-jaqueryajax-ne-otpravlyaet-moj-seansovyij-cookie/41995251#41995251), и сделать следующее.
1) Добавьте следующее в ваш запрос ajax.
xhrFields: { withCredentials:true }
2) Добавьте следующее в заголовки ответа для ресурсов в другом поддомене.
Access-Control-Allow-Origin : http://original.mydomain.com
Access-Control-Allow-Credentials : true
Попробовав другие решения и все еще не заставив их работать, я выяснил, в чем проблема в моем случае. Я изменил contentType с "application/json" на "text/plain".
$.ajax(fullUrl, {
type: "GET",
contentType: "text/plain",
xhrFields: {
withCredentials: true
},
crossDomain: true
});
У меня возникла та же проблема, и при некоторых проверках мой скрипт просто не получал cookie-файл sessionid.
По значению cookie-файла sessionid в браузере я выяснил, что мой фреймворк (Django) передавал cookie-файл sessionid с HttpOnly по умолчанию. Это означало, что скрипты не имели доступа к значению sessionid и поэтому не передавали его вместе с запросами. Довольно смешно, что HttpOnly будет значением по умолчанию, когда так много вещей используют Ajax, что потребует ограничения доступа.
Чтобы исправить это, я изменил настройку (SESSION_COOKIE_HTTPONLY=False), но в других случаях это может быть флаг "HttpOnly" на пути к cookie
Если вы разрабатываете на localhost
или порт на локальном хосте, такой как localhost:8080
в дополнение к шагам, описанным в ответах выше, вам также необходимо убедиться, что вы не передаете значение домена в заголовке Set-Cookie.
Вы не можете установить домен на localhost
в заголовке Set-Cookie - это неправильно - просто опустите домен.
См. Файлы cookie на локальном хосте с явным доменом и Почему asp.net не создает куки на локальном хосте?
Эта ошибка возникает при попытке отправить межсайтовый запрос. Как мне решить эту проблему?
В файле конфигурации nginx я добавил
add_header Access-Control-Allow-Origin '*.domain.com'
add_header Access-Control-Allow-Credentials 'true';
И в «domain.com» я пытаюсь отправить запрос ajax с
$.ajax({
url: sub.domain.com,
xhrFields: {
withCredentials: true
}
});
Добавление моего сценария и решения на случай, если это поможет кому-то другому. Я столкнулся с подобным случаем при использовании RESTful API. Мой веб-сервер, на котором размещены файлы HTML/Script/CSS, и API-интерфейсы сервера приложений размещались в одном домене. Однако путь был другим.
веб-сервер - mydomain / webpages/abc.html
использовал abc.js, который установил cookie с именем mycookie
сервер приложений - mydomain / webapis / servicename.
на какие вызовы API были сделаны
Я ожидал, что файл cookie находится в mydomain / webapis / servicename, и попытался прочитать его, но он не отправлялся. Прочитав комментарий к ответу, я проверил в инструменте разработки браузера, что путь mycookie установлен на "/ webpages " и, следовательно, недоступен при вызове службы для
mydomain / webapis / servicename
Итак, при установке cookie из jquery я сделал вот что:
$.cookie("mycookie","mayvalue",{**path:'/'**});
Просто мои 2 цента при установке проблемы с файлом cookie PHPSESSID при работе на локальном хосте и в среде разработки. Я делаю AJAX-вызов к моей конечной точке REST API на locahost. Скажите, что его адрес mysite.localhost/api/member/login/
(Виртальный хозяин в моей среде разработки).
Когда я делаю этот запрос на Почтальон, все идет хорошо, и 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 выше
Вы должны инициализировать сеанс, прежде чем пытаться войти в систему.
Для PHP, вы должны сделать
session_start();
на странице, с которой вы начинаете вход AJAX вызова.
Таким образом SESSIONID
Будет создан и сохранен файл cookie браузера. И отправляется вместе с заголовком запроса во время вызова ajax, если вы делаете запрос ajax в тот же домен
Для последующих вызовов ajax браузер будет использовать SESSIONID
которые изначально были созданы и сохранены в cookie-файлах браузера, если только мы не удалили cookie-файл браузера или не вышли из системы (или не установили другой cookie)
Возможно, не на 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");
Погружение в журнал, и я быстро обнаружил пропущенную сессию, где не было отправлено печенье.