Я пытаюсь получить файлы cookie, которые я устанавливаю на сервере, используя PlayFramework:
response().setHeader(SET_COOKIE, AppConstants.COOKIE_USER_SESSIONID+"="+appSession.getSid());
в угловом приложении, но я не в состоянии.
Если я использую клиент Advanced Rest, я получаю заголовок SetCookie и файлы cookie устанавливаются в следующем вызове. Однако, когда я вызываю одно и то же api через мое угловое приложение, я не могу получить заголовок в ответе и, следовательно, не куки для приложения.
Вот что я уже пробовал:
Должен быть некоторый улов в угловом коде, который я не могу понять. Любая помощь по этому поводу высоко ценится. Благодарю.
Угловые фрагменты кода:
LoginController:
angular.module('wratApp')
.controller('LoginCtrl', function (postService, wratSettings, wratRoutes, $location, $cookies) {
$("#header").hide();
this.user= {};
this.logUserin = function(){
console.log("User: " + this.user.email + " & pwd: " + this.user.pwd);
var payLoad = {};
payLoad.ldap = this.user.email;
payLoad.pwd = this.user.pwd;
postService.postPromise(wratRoutes(wratSettings).POST_USER_LOGIN(),payLoad)
.then(function(){ //login success
console.log("login success");
$location.path(wratRoutes().CLIENT_HOME());
}, function(){ //error in login
console.log("Login failed");
})
;
}
});
PostService:
angular.module('wratApp')
.factory('postService', function ($http, $q, $cookies, $location) {
function postService() {
var self = this;
self.postPromise = function (uri,payload){
var deferred = $q.defer();
$http.post(uri,payload)
.success(function(data, status, headers, config){
console.log("Got response cookies: "+$cookies.getAll());
deferred.resolve(data);
})
.error(function(data, status, headers, config){
if(status == 401){
angular.forEach($cookies.getAll(), function (v, k) {
$cookies.remove(k);
});
$location.path('/login');
}else{
deferred.reject(data);
}
});
return deferred.promise;
}
}
return new postService();
});
Теперь мой логин успешно завершен, но без файлов cookie, установленных сервером. Кроме того, cookie PlaySession, который каким-то образом отображается в отладчике (установленные вручную из него даже отсутствуют в отладчике), не находится в переменной $ cookie с угловым значением (см. Рисунок ниже).
Пожалуйста, предложите, как я могу это решить. Благодарю.
Обновление 1:
Если я запускаю сервер воспроизведения не в режиме отладки, файлы cookie соответствующим образом отправляются сервером. Это проблема с угловым приложением, когда в следующем вызове он не переносит значения из заголовка Set-Cookie в файлы cookie для следующего вызова. Возможно, это и глупая ошибка на моем конце. Пожалуйста, посмотрите, можете ли вы помочь мне разобраться.
Ответ сервера/логин:
HTTP/1.1 200 OK
Vary: Origin
Set-Cookie: sid=1e6823e24554598b0521ca5f64d7746b; Path=/
Set-Cookie: PLAY_SESSION=953d9d5730bf1b77cccaadef6b78c209e59d924b-sid=1e6823e24554598b0521ca5f64d7746b; Path=/; HTTPOnly
Content-Type: application/json; charset=utf-8
Access-Control-Allow-Origin: http://wrat.com:9009
Access-Control-Allow-Methods: OPTIONS, GET, POST
Access-Control-Allow-Credentials: true
Date: Thu, 24 Sep 2015 22:27:03 GMT
Content-Length: 429
Следующий запрос, который должен содержать cookie, но без файлов cookie :-(:
GET /products/all HTTP/1.1
Host: wrat.com:9000
Accept: application/json, text/plain, */*
Origin: http://wrat.com:9009
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93 Safari/537.36
Referer: http://wrat.com:9009/
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
Снятие тега платформы Play, так как это не проблема с воспроизведением.
Добавление опции withCredentials в вызовы $ http работало для меня и разрешило проблему.
$http.post(uri,payload, {withCredentials: true})
Проблема связана с вызовами ajax, где, если флаг withCredentials не правдоподобен как на сервере, так и на клиенте, cookie, установленные сервером, не поддерживаются для вызовов с перекрестным происхождением. Следовательно, это полностью игнорировало файлы cookie, которые я устанавливал с сервера.
Текст из следующего вопроса помог решить проблему:
Почему метод jQuery.ajax() не отправляет мой cookie сеанса?
из:
Я работаю в междоменном сценарии. Во время входа в систему удаленный сервер возвращает заголовок Set-Cookie вместе с параметром Allow-Access-Control-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/)
Зачем?
Вы не можете получить значение 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:
Важное примечание: при ответе на запрос с полномочиями сервер должен указать домен и не может использовать wild carding. Вышеприведенный пример потерпит неудачу, если заголовок был подстановочным знаком: Access-Control-Allow-Origin: *
Поэтому, когда запрос:
Происхождение: http://foo.example Cookie: pageAccess = 2 Сервер должен ответить:
Access-Control-Allow-Origin: http://foo.example Access-Control-Allow-Credentials: true
[полезная нагрузка] В противном случае полезная нагрузка не будет возвращена скрипту. См. Https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials.