wake-up-neo.com

Kann ich eine nicht autorisierte 401-UND-Weiterleitung (mit Standort) senden?

Ich möchte einen 401 Unauthorized schicken UND den Client irgendwo umleiten. Jedoch:

wenn ich es so mache:

header('HTTP/1.1 401 Unauthorized');
header('Location: /');

der Server sendet einen 302 Found mit Location, also keinen 401 Unauthorized.

Wenn ich es so mache:

header('Location: /');
header('HTTP/1.1 401 Unauthorized');

der Browser empfängt sowohl einen 401 Unauthorized als auch eine Location, leitet jedoch keine Weiterleitung ein.

(IE 9 und Chrome 16 verhalten sich dasselbe, also vermute ich, dass es korrekt ist)

Vielleicht missbrauche ich HTTP? Ich möchte, dass meine App-Oberfläche für alle Clients genau gleich ist: Textbrowser, moderner Browser, API-Aufrufe usw. Der Antworttext 401 + würde einem API-Benutzer sagen, was was ist. Die Weiterleitung ist nützlich für einen Browser.

Gibt es einen (guten) Weg?

35
Rudie

Per Definition (siehe RFC 2616 ) ist der HTTP 302-Antwortcode der Weiterleitungscode. Andernfalls kann der Standortheader ignoriert werden.

Sie können jedoch eine HTTP 401-Antwort senden und trotzdem die Ausgabe anzeigen. Anstatt den Benutzer auf eine Fehlerseite umzuleiten, können Sie einfach den Inhalt, den Sie senden möchten, in dieselbe HTTP-Nachricht schreiben.

27
David Chan

Ich komme sehr spät hierher, aber ich dachte, ich würde meine zwei Cent hinzufügen. Soweit ich es verstehe, möchte ich darauf hinweisen, dass der Benutzer nicht über die richtige Berechtigung verfügt, und er muss aufgefordert werden, sich einzuloggen. Rudie möchte verständlicherweise 401 Unauthorized zurückgeben (da der Benutzer durch einen Mechanismus autorisieren muss, z. B. Protokollierung) in) und leiten sie auch an die Anmeldeseite weiter - dies ist jedoch nicht sehr einfach zu bewerkstelligen und wird von den meisten Bibliotheken nicht standardmäßig unterstützt. Eine Lösung besteht darin, die Anmeldeseite im Text der 401-Antwort anzuzeigen, wie in einer anderen Antwort vorgeschlagen. Lassen Sie mich dies jedoch aus der Perspektive etablierter/bester Praktiken betrachten.

Testfall 1: Facebook

Wenn Sie zu einer geschützten Facebook-Seite (meinem Benutzerprofil) navigieren, während Sie abgemeldet sind, erhalten Sie eine 404 Not Found-Antwort. Facebook dient einer allgemeinen Seite "Diese Seite ist nicht verfügbar", die auch ein Anmeldeformular enthält. Interessant. Noch interessanter: Wenn ich zur "Ereignisseite" navigiere, wird mir eine 302-Antwort angezeigt, die zu einer Anmeldeseite weiterleitet (die eine 200-Antwort zurückgibt). Ich denke, ihre Idee ist, 302 für Seiten zurückzugeben, von denen wir know existieren, aber 404 für Seiten, die möglicherweise existieren oder nicht (z. B. um die Privatsphäre eines Benutzers zu schützen).

Testfall 2: Google Posteingang

Das Navigieren zu meinem Posteingang, wenn ich abgemeldet bin, gibt 302 zurück und leitet mich zu einer Anmeldeseite weiter, ähnlich wie bei Facebook. Ich konnte nicht herausfinden, wie ich mein Google+ Profil privat machen kann, also keine Testdaten dort ...

Testfall 3: Amazon.com

Das Navigieren zu meinem Bestellverlauf bei Abmeldung gibt 302 zurück und leitet mich wie zuvor an eine Anmeldeseite weiter. Amazon hat keine Vorstellung von einer "Profil" -Seite, daher kann ich das hier auch nicht testen.

Um die Testfälle hier zusammenzufassen, scheint es die beste Vorgehensweise zu sein, eine 302 Found zurückzugeben und an eine Anmeldeseite weiterzuleiten, wenn sich der Benutzer anmelden muss (obwohl ich behaupte, dass 303 See Other eigentlich eher geeignet ist). Dies ist natürlich nur dann der Fall, wenn ein echter menschlicher Benutzer einen Benutzernamen und ein Passwort in einem HTML-Formular eingeben muss. Für andere Authentifizierungsarten (z. B. Basisschlüssel, API-Schlüssel usw.) ist 401 Unauthorized offensichtlich die geeignete Antwort. In diesem Fall ist keine Weiterleitung auf eine Anmeldeseite erforderlich.

11
tytk

3xx bedeutet Weiterleitung
4xx bedeutet, dass der Browser etwas falsch gemacht hat.

Es gibt einen Grund, warum die Codes so aufgeteilt sind wie sie sind - sie mischen sich nicht;)

6

Zusätzlich zu den guten Antworten von Kolink und David (+1) möchte ich darauf hinweisen, dass Sie versuchen, die Semantik des HTTP-Protokolls zu ändern, indem Sie beide eine 401 zurückgeben und dem Browser die Umleitung mitteilen. So soll das HTTP-Protokoll nicht funktionieren. Wenn Sie einen Weg finden, um dieses Ergebnis zu erzielen, werden HTTP-Clients das Verhalten Ihres Dienstes als nicht standardmässig empfinden.

Entweder senden Sie eine 401 und geben dem Browser die Möglichkeit, damit umzugehen, oder Sie behandeln die Situation anders (z. B. wie ein Kommentator vorgeschlagen hat, leiten Sie auf eine Anmeldeseite oder möglicherweise auf eine Seite um, in der erläutert wird, warum der Benutzer keinen Zugriff hatte).

4
Eric J.

Hier ist ein sauberer Weg:

Auf der 401-Seite können Sie die zu sendende "Ansicht" basierend auf dem "Accept" -Header in der Anforderung auswählen.

Wenn der Accept-Code application/json ist, können Sie den Hauptteil einfügen:

{"status":401;"message":"Authentication required"}

Wenn "Accept" text/html lautet, können Sie den Textkörper einfügen:

<form action="/signin" method="post">
    <!-- bla bla -->
    <input type="hidden" name="redirect" value="[URL ENCODE REQUEST URI]">
</form>

Dann stoßen Sie auf die gleiche Frage ... geben Sie bei erfolgreichem Login einen 200 OK oder einen 302 Found aus? (siehst du was ich dort gemacht habe? )

Wenn Sie die Authentifizierung auf einer beliebigen Seite ausführen können, können Sie die Formularaktion lediglich über dieselbe Seiten-URL einrichten. Wenn Sie jedoch den vom Benutzer angegebenen request_uri in das Formularaktionsattribut setzen, gilt watch für XSS.

2
Frank Forte

Sie können 401 senden und dann im Antworttext window.location = 'domain.com' senden. Der Benutzer wird jedoch sofort weitergeleitet, ohne zu wissen, dass 401 aufgetreten ist.

1
rkosegi

Webbrowser sind keine REST -Clients. Bleiben Sie beim Sendestatus 200 mit einem Location-Header und ohne Inhalt. Die 30x-Weiterleitungen gelten für Seiten, die verschoben wurden. Es sollte nicht erwartet werden, dass ein anderer Statuscode/Standortheader in einem Webbrowser umgeleitet wird.

Alternativ hat Ihr Webserver möglicherweise konfigurierbare Fehlerseiten. Sie können zur Fehlerseite Javascript zur Umleitung hinzufügen.

0
Jeff Harris