2014-06-09 9 views
24

Ich baue eine AngularJS (1.2.16) Web App mit einer RESTful API, und ich möchte 401 nicht autorisierte Antworten für Anfragen senden, bei denen Authentifizierungsinformationen ungültig oder nicht vorhanden sind. Wenn ich dies tue, sehe ich, selbst wenn ein HTTP-Interceptor vorhanden ist, den browserpräsentierten Basisdialog "Authentication Required", wenn über AngularJS eine AJAX-Anfrage gestellt wird. Mein Interceptor läuft nach dieser Dialog, der zu spät ist, etwas Nützliches zu tun.Verhindern von HTTP Basic Auth Dialog mit AngularJS Interceptors

Ein konkretes Beispiel:

My Back-End-API gibt 401 für /api/things es sei denn, ein Autorisierungs-Token vorhanden ist. Schön und einfach.

$httpProvider.interceptors.push(['$q', function ($q) { 
    return { 
    'responseError': function (rejection) { 
     if (rejection.status === 401) { 
     console.log('Got a 401') 
     } 
     return $q.reject(rejection) 
    } 
    } 
}]) 

Wenn ich meine App laden, entfernen Sie die Authentifizierungs-Token, und führen Sie ein:

Auf der AngularJS App Seite, ich habe einen Abfangjäger wie dies im config Block am docs und eingerichtet sah AJAX Aufruf /api/things (um hoffentlich den obigen Interceptor triggern), sehe ich:

Authentication Required

Wenn ich das Dialog abzubrechen, ich sehe den Ausgang console.log „Got a 401“, die ich hatte gehofft, anstelle dieses Dialog zu sehen:

Got a 401

klar, dass die Abfangjäger funktioniert, aber es ist zu spät abfängt!

Ich sehe zahlreiche Postings im Web bezüglich der Authentifizierung mit AngularJS in Situationen wie dieser, und sie alle scheinen HTTP-Interzeptoren zu verwenden, aber keiner von ihnen erwähnt den grundlegenden Auth-Dialog, der auftaucht. Einige falsche Gedanken, die ich für sein Aussehen hatte:

  • Fehlende Content-Type: application/json Header auf die Antwort? Nein, es ist da.
  • Müssen Sie etwas anderes als Versprechen Ablehnung zurückgeben? Dieser Code wird immer nach dem Dialog ausgeführt, unabhängig davon, was zurückgegeben wird.

Vermisse ich einen Setup-Schritt oder den Interceptor falsch?

+0

Warum hast du 403 statt 401 nicht benutzt? –

+0

Ich habe eine 401 verwendet, weil ich in der ursprünglichen Frage das Authentifizierungstoken entfernt habe (in meinem Fall ein Cookie). 401 ist der richtige Antwortcode, der hier verwendet werden soll, da die Anforderung Authentifizierung erfordert und keine bereitgestellt wurde. 403 ist für die Authentifizierung vorgesehen, aber der Server verweigert den Zugriff auf die Ressource. –

Antwort

12

Ich habe es herausgefunden!

Der Trick bestand darin, einen Antwortkopf WWW-Authenticate eines anderen Werts als Basic zu senden. Sie können dann die 401 mit einem grundlegenden $http Interceptor, oder etwas noch schlauer wie angular-http-auth erfassen.

+6

Können Sie das bitte näher ausführen? "Etwas noch schlauer wie angular-http-auth" erfordert, dass der Server eine Antwort von 200 sendet. Ich suche nach einer Lösung, wo der Server einen 401-Code zurückgibt. – Romain

+0

Ich denke, es erscheint nur Popup, wenn 'Authorization': 'Basic XXX' – killebytes

+0

bitte poste einige Codebeispiel Ich habe das gleiche Problem. Die IOS-Basisauthentifizierungsanfrage endet nie –

1

Für die Zukunft

ich mit dieser Lösung habe kommen, wenn 401 Fehler zu behandeln versucht. Ich hatte nicht die Möglichkeit, Basic zu x-Basic10 oder etwas Ähnliches umzuschreiben, also habe ich mich entschieden, es auf Klientenseite mit Angular zu behandeln.

Wenn Sie eine Abmeldung starten, versuchen Sie zunächst, eine falsche Anforderung mit einem falschen Benutzer zu stellen, um die aktuell zwischengespeicherten Anmeldeinformationen zu verwerfen.

Ich habe diese Funktion, um die Anfragen zu tun (es ist mit jQuerys $.ajax mit behinderten asynch Anrufen):

function authenticateUser(username, hash) { 
    var result = false; 
    var encoded = btoa(username + ':' + hash); 

    $.ajax({ 
     type: "POST", 
     beforeSend: function (request) { 
      request.setRequestHeader("Authorization", 'Basic ' + encoded); 
     }, 
     url: "user/current", 
     statusCode: { 
      401: function() { 
       result = false; 
      }, 
      200: function (response) { 
       result = response; 
      } 
     }, 
     async: false 
    }); 

    return result; 
} 

Also, wenn ich versuche, einen Benutzer anzumelden, dies geschieht:

//This will send a request with a non-existant user. 
//The purpose is to overwrite the cached data with something else 
accountServices.authenticateUser('logout','logout'); 

//Since setting headers.common.Authorization = '' will still send some 
//kind of auth data, I've redefined the headers.common object to get 
//rid of the Authorization property 
$http.defaults.headers.common = {Accept: "application/json, text/plain, */*"}; 
8

I hatte dieses Problem zusammen mit Spring Boot Security (HTTP Basic), und seit Angular 1.3 müssen Sie $httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest'; für das Popup nicht angezeigt werden.

+1

es funktioniert nicht für meine app mit Angular 1.5 und firefox 48.x ... die basis auth prompt wird auch mit X-Requested-With header ausgelöst ... – ptitjuju69

+0

Selbe für mich. Ich hatte diesen Header in Postbote hinzugefügt. aber es funktioniert nicht. –

+1

das ist mein Problem gelöst. Browser-Authentifizierungsmodus wurde ausgeblendet, nachdem das Problem behoben wurde. Vielen Dank. – luffy

Verwandte Themen