it-swarm.com.de

$ http Antwort Set-Cookie nicht zugänglich

Ich schreibe gerade ein Anglejs-Frontend für mein Backend und stoße auf ein etwas häufiges Problem:

Der Server sendet ein Cookie in einer Antwort zurück, wird jedoch von angle.js vollständig ignoriert (der Wert 'Set-Cookie' kann nicht einmal ausgedruckt werden).

Ich habe versucht zu lesen

Set-Cookie im HTTP-Header wird mit AngularJS ignoriert

Angularjs $ http scheint "Set-Cookie" in der Antwort nicht zu verstehen

aber ich habe leider alle lösungen dort ausprobiert und scheint einfach nicht zu funktionieren.

Anfrage gesendet

(as captured by Chrome Developer Tools)

Antwort erhalten

(as captured by Chrome Developer Tools)

Ich benutze eckige.js (v1.2.10), und das war es, was ich für die Anfrage verwendet habe

$http.post('/services/api/emailLogin',
           sanitizeCredentials(credentials), 
           {
              withCredentials: true
           }).success(function(data, status, header) {
                console.log(header('Server'));
                console.log(header('Set-Cookie'));
                console.log(header('Access-Control-Allow-Headers'));
                console.log(header('Access-Control-Allow-Methods'));
                console.log(header);
            }).then(
                function(response) {
                    console.log(response);
                    return response.data;
                });

withCredentials=true wird auf der Clientseite vor der Anforderung festgelegt. 

Access-Control-Allow-Credentials=true wird serverseitig festgelegt, bevor die Antwort zurückgegeben wird.

In den Antwortheader der Chrome Developer Tools ist eindeutig Set-Cookie zu sehen, der Ausdruck ist jedoch nur

(code printout)

Nur Set-Cookie im Antwortheader wird nicht gedruckt. Ich frage mich, warum dies passiert. Gibt es eine Möglichkeit, sicherzustellen, dass withCredentials=true tatsächlich gesetzt ist (ich habe es nicht im Anforderungsheader gesehen)?

Jede Hilfe wird geschätzt!

24
Luke

Ich habe in $httpBackend Quellcode geschaut:

xhr.onreadystatechange = function() {

  // some code

  if (xhr && xhr.readyState == 4) {
    var responseHeaders = null,
        response = null;

    if(status !== ABORTED) {
      responseHeaders = xhr.getAllResponseHeaders();

      // some code

Es verwendet XMLHttpRequest#getAllResponseHeaders, um die Antwortheader abzurufen.

Nach einer kurzen Suche fand ich diese Frage: xmlHttp.getResponseHeader + Funktioniert nicht für CORS

Das hat mir bewusst gemacht, dass XHR durch seine Spezifikation SET-COOKIE nicht unterstützt, also hat es nichts mit winkl.js zu tun.

http://www.w3.org/TR/XMLHttpRequest/#the-getallresponseheaders%28%29-method

4.7.4 Die getAllResponseHeaders () -Methode

Gibt alle Header der Antwort zurück, mit Ausnahme derjenigen, deren Feldname Set-Cookie oder Set-Cookie2 ist.


Verwenden Sie stattdessen einfach $cookies :

Es ist ein anderes Modul, also müssen Sie es zu Ihren Skripten hinzufügen

 <script src="angular.js"></script>
 <script src="angular-cookies.js"></script>

Und fügen Sie es den Modulabhängigkeiten hinzu: 

 var app = angular.module('app',['ngCookies']);

Dann benutze es einfach so:

app.controller('ctrl',  function($scope, $http , $cookies, $timeout){

  $scope.request = function(){

    $http.get('/api').then(function(response){
      $timeout(function(){
        console.log($cookies.session)
      });         
    })
  }
})

Ich verwende $timeout, da $cookies erst nach einem Digest mit den Cookies des Browsers synchronisiert wird.

29
Ilan Frumer

Müssen Sie das Cookie tatsächlich in Angular lesen oder reicht es aus, wenn es vom Browser gesetzt und an weitere Anfragen weitergeleitet wird? Während ich den ersten nicht zum Laufen bringen konnte, konnte ich den letzteren mit einer sehr ähnlichen Konfiguration ziemlich schnell zum Laufen bringen. (Insbesondere konnte ich $cookies nicht als von @Ilan empfohlen verwenden. Es wurde nichts zurückgegeben.)

Zuerst sollten Sie auf der Seite Angular den $httpProvider so konfigurieren, dass withCredentials standardmäßig gesendet wird:

app.config(['$httpProvider', function($httpProvider) {
    $httpProvider.defaults.withCredentials = true;
}]);

Das ist alles, was Sie in Angular tun müssen. Wenn Sie versuchen, $cookies zu lesen, kann der Cookie an dieser Stelle zwar immer noch nicht angezeigt werden, er wird jedoch gespeichert und bei zukünftigen Aufrufen von AJAX übergeben.

Auf dem Server müssen Sie dann eine bestimmte Domäne (oder eine Gruppe von Domänen) zusammen mit dem Access-Control-Allow-Credentials-Header angeben, die unter CORS zulässig ist. Mein Backend ist Flask in Python mit Flask-Restful und es sieht so aus:

import Flask
from flask_restful import Api
app = Flask(__name__)
api = Api(app)
api.decorators = [cors.crossdomain(Origin='http://localhost:8100', credentials=True)]

Das ist alles was es brauchte. Jetzt setzt Angular (oder vielmehr der Browser) den Cookie und gibt ihn mit zukünftigen Anforderungen vollständig transparent zurück!

(Der gleiche Punkt wird hier gemacht: https://stackoverflow.com/a/19384207/2397068 .)

4
Lane Rettig

Sie müssen Ihre .htaccess-Datei so ändern, dass die Header gelesen werden können.

Header set Access-Control-Allow-Headers Content-Type
0
DDT

In Angular 1.3.14 funktioniert es nicht mehr.

Ich hatte das gleiche Problem. Ich verwende $ resource und erklärte withCredentials: true.

 var fooRes = $resource('/address/exemple',
    {},
    {
        bar: {
            method: 'POST',
            withCredentials: true,
        }
    }
 );

 fooRes.bar({
     "stuff" : "lorem"
 }).$promise.then(function(){
     //callback
 })

oder Sie können den Header "Access-Control-Allow-Credentials" auf "true" setzen.

Nun wird der Cookie gespeichert und Sie können $ Cookie verwenden.

Ich hoffe es wird helfen.

0
hugodutra