Наконец-то я смог найти проблему. Путешествие было более приятным, чем результат, поэтому позвольте мне разбить его на шаги, которые я предпринял для решения своей проблемы.
В итоге, это не проблема с Angular. На куки, которую я отправлял, был установлен флаг secureCookie
. Когда я тестировал свое приложение без https
, похоже, что угловое приложение не использовало (или не получало доступ) заголовок Set-Cookie
, полученный в 200 OK
.
Мой исходный код для отправки запроса входа на сервер и обработки его ответа был
return this.http.post(this.SIGNIN_USER_URL,body,httpOptions)
.map(response=>{
console.log('response from backend service',response);
let result= <ServerResponse>response;
console.log("result is "+result.result+' with additional information '+result.additionalInformation)
return result;
})
.catch(this.handleError);
Я не использовал опцию observe: 'response'
, что означало, что ответ будет содержать только тело, а не заголовки. Я изменил код на следующий, чтобы видеть, какие заголовки принимаются.
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' }),
withCredentials: true,
observe: 'response' as 'response'
};
public signinUser(user:UserSigninInfo):any{
console.log('contacting server at '+this.API_URL +this.SIGNIN_USER_URL +" with user data "+user+ " with httpOptions "+httpOptions.withCredentials + ","+httpOptions.headers );
let signinInfo= new UserSignin(user);
let body = JSON.stringify(signinInfo);
return this.http.post(this.SIGNIN_USER_URL,body,httpOptions)
.catch(this.handleError);
}
Вышеуказанный код вызывался следующим образом. Я изменяю это, чтобы получить заголовки в ответе
return this.bs.signinUser(user).subscribe((res:HttpResponse<any>)=>{console.log('response from server:',res);
console.log('response headers',res.headers.keys())
} );
Я также создал перехватчик для печати входящих и исходящих сообщений (скопировано из SO)
import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse} from "@angular/common/http";
import {Injectable} from "@angular/core";
import {Observable} from "rxjs/Observable";
import 'rxjs/add/operator/do';
@Injectable()
export class CustomInterceptor implements HttpInterceptor {
constructor() {
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
console.log("outgoing request",request);
request = request.clone({
withCredentials: true
});
console.log("new outgoing request",request);
return next
.handle(request)
.do((ev: HttpEvent<any>) => {
console.log("got an event",ev)
if (ev instanceof HttpResponse) {
console.log('event of type response', ev);
}
});
}
}
Когда я начал отладку, я заметил, что хотя сервер отправлял 10 заголовков, только 9 печатались
заголовки с сервера
Распечатать сообщение на консоли (Set-Cookie
отсутствует! Заголовок, необходимый моему приложению для получения файла cookie для аутентификации)
0: "Content-Length"
1: "Content-Security-Policy"
2: "Content-Type"
3: "Date"
4: "Referrer-Policy"
5: "X-Content-Type-Options"
6: "X-Frame-Options"
7: "X-Permitted-Cross-Domain-Policies"
8: "X-XSS-Protection"
length: 9
Это дало мне указание, что приложение не видит заголовок Set-Cookie
. Я думал, что смогу решить эту проблему, добавив политику CORS
в инфраструктуру игры exposedHeaders = ["Set-Cookie"]
, но это не сработало. Позже я посмотрел поближе на печенье и заметил secureCookie
setting
Set-Cookie: id=...Secure; HTTPOnly
Это заставило меня подумать, что, возможно, мои настройки cookie не соответствуют моей среде (localhost, без HTTPS). Я изменил настройки файлов cookie в Silhoutte
val config = CookieAuthenticatorSettings(secureCookie=false)
И это сработало!
Хотя приведенный выше код работает для secureCookie, и с Angular это не было проблемой, я надеюсь, что некоторые люди сочтут этот подход полезным