Relogin und HTTP Basic Auth

Webentwickler sind sich seit langem des Problems der Anmeldung und Anmeldung bei Websites bewusst, die durch die HTTP-Basisautorisierung geschützt sind. Obwohl es andere Authentifizierungsmethoden gibt, bei denen dieses Problem nicht auftritt, ist die Basisautorisierung häufig die beste Wahl. Das Netzwerk verfügt über genügend Materialien, die verschiedene allgemeine und spezielle Lösungen beschreiben. Aber alle, die ich leider gefunden habe, beschreiben nur einige Teillösungen, die in einem Browser funktionieren und in einem anderen nicht funktionieren. Unter Katze gebe ich ein allgemeines Endergebnis meiner Forschung zu diesem Problem

Ich werde sofort reservieren, dass ich kein Front-End-Entwickler bin, und ich habe nicht auf die gesamte Vielfalt der Marken- und Browserversionen eingegangen. Nur Mainstream mit zum Zeitpunkt des Schreibens relevanten Versionen. Für die meisten Webaufgaben reicht dies aus. Für Entwickler, die Unterstützung für den gesamten "Zoo" von Browsern benötigen, kann der Artikel ein guter Ausgangspunkt sein.

Das Problem besteht im Wesentlichen darin, dass der Standard für die HTTP-Basisautorisierung keine Protokollierung vorsieht. Allgemein. Wenn Sie zu einer durch die Basisautorisierung geschützten Seite gehen, zeigt Ihnen der Browser selbst ein eigenes Fenster mit einer Anforderung für die Anmeldung / das Kennwort an und speichert diese bei erfolgreicher Anmeldung irgendwo in der Tiefe. Bei allen nachfolgenden Anforderungen an andere geschützte Seiten dieser Site werden diese Werte automatisch im Autorisierungsheader verwendet:
Autorisierung: Basic bm9uZTpub25l
Dabei ist bm9uZTpub25l der Base64-codierte Login- / Passwort-Link none: none (Ihr Benutzername und Passwort können unterschiedlich sein).

Um sich anzumelden, müssen Sie nur den alten Benutzernamen / das alte Passwort in diesen Tiefen des Browsers und auf diesen zurücksetzen Ort, um neue aufzunehmen. Hier erwartet uns eine Überraschung. Da kein Standard diese Aktion regelt, tut dies jeder Browser nach eigenem Verständnis.

Schlimmer noch, da das Anmelde- / Kennwortanforderungsfenster ein eigenes Browserfenster ist, das bereits nur auf HTTP-Seitenkopfzeilen reagiert, wird dieses Fenster vor jeder Verarbeitung des Seitenkörpers angezeigt. Das heißt, das Ausführen von Javascript beim Empfang einer Serverantwort mit dem Status 401 funktioniert nicht. Vor dem Benutzer wird dieses Fenster immer wieder mit einer wiederholten Anfrage nach Login / Passwort geöffnet.

In der Tat ist dieser Punkt von entscheidender Bedeutung, da für fast alle Browser die einzige Möglichkeit zum Abmelden darin besteht, eine Anfrage mit offensichtlich falschem Login / Passwort an den Server zu senden, eine Serverantwort mit dem Status 401 zu erhalten und dann den Login / Passwort-Cache des Browsers zurückzusetzen. Wenn der Browser es Ihnen jedoch gleichzeitig nicht erlaubt, die Antwort 401 zu verarbeiten und den Anmeldevorgang bereits für den neuen Benutzer fortzusetzen, die Kontrolle bereits beim Lesen von HTTP-Headern zu übernehmen und genau die Form der Autorisierung zu aktivieren, in die Sie sie eingeben, funktioniert dies nicht in Ihrem Gesicht schon ein problem. Es spielt keine Rolle, ob dies eine normale Anforderung per Referenz oder XMLHttpRequest oder Abruf ist. Der Browser übernimmt weiterhin die Kontrolle beim Parsen der Header.

Damit…

Ausgangsdaten:


  1. Es gibt eine separate logout.html-Seite, auf der sich die gesamte Logik im Javascript-Skript befindet, von der Teile im Verlauf der Präsentation angegeben werden
  2. URL angegeben - Seitenadresse, die nach erfolgreicher Anmeldung umgeleitet werden soll
  3. Url401 wird angegeben - die Adresse der Seite, die immer den HTTP 401-Fehler zurückgibt (nicht autorisiert)

// file logout.html
const url = new URL("http://mysite.com/");
const url401 = new URL("http://mysite.com/401");

Internet Explorer


Unser Produkt benötigt keine Unterstützung für diesen Browser, daher habe ich die Lösung nicht persönlich getestet. Trotzdem gibt es laut Google eine Lösung dafür, und es ist vielleicht die einfachste und eleganteste von allen. Außerdem habe ich nie Informationen darüber erhalten, dass diese Lösung für Microsoft-Browser ihre Relevanz verloren hat:

if (document.execCommand("ClearAuthenticationCache")) {
    window.location.assign(url);
}

Im IE gibt es eine ClearAuthenticationCache-Methode, die "diese sehr tiefen Eingeweide" verwirft. Einfach und elegant. Und kein Tanzen mit der Hilfsseite 401. Ich weiß nicht, ob diese Methode in Edge funktioniert. Wahrscheinlich ja.

Das Konstrukt document.execCommand gibt true zurück, wenn die Methode vorhanden und "funktioniert" ist. Anschließend leitet window.location.assign (url) den Benutzer zur Eingabe eines neuen Benutzernamens und Kennworts weiter

Firefox (72.0.1)


Im Rahmen unserer Aufgabe ist dies der problematischste Browser. Für ihn gibt es noch keine vollständige Lösung. Seit 15 bis 20 Jahren hängt eine Anfrage für das angegebene Problem im Bug-Tracker des Entwicklerteams. Aber "die Dinge sind immer noch da." Das Maximum, das erreicht werden kann, ist das Kurven-Razlogin.

Eingabe:
Firefox setzt den Kennwortcache nicht zurück, nachdem eine 401-Antwort über XMLHttpRequest oder eine Abrufanforderung empfangen wurde. Nur durch eine regelmäßige Anfrage mit dem Login / Passwort in der URL selbst. Das heißt, so etwas wie
http: // none: none@mysite.com/
Der Code:

else if (/firefox|iceweasel|fxios/i.test(window.navigator.userAgent)) {
    url.username = 'none';
    url.password = 'none';
    window.location.assign(url);
}

Danach erhält der Benutzer ein Anmelde- / Passworteingabeformular, in das alles, was Sie eingeben, immer wieder eingeblendet wird. Tatsache ist, dass die eingegebenen Werte die in der URL angegebenen Anmelde- / Kennwortwerte nicht überschreiben. Das heißt, anstelle der eingegebenen Werte wird eine Reihe von none: none wird jedes Mal zum Server gesendet. Um sich unter einem anderen Namen anzumelden, muss der Benutzer auf Abbrechen klicken, zur Startseite (http: //mysite.com/) gehen und dort ein neues Login / Passwort eingeben.

Krumm? Aber leider gibt es keine andere Lösung

Google Chrome (79.0.3945.88)


Für Chrome funktioniert die Abrufmethode hervorragend. XMLHttpRequest funktioniert jedoch nicht (((Der Cache wird nicht geleert und die Protokollierung findet nicht statt). Außerdem habe ich versucht, die Anmeldung / das Kennwort sowohl als Parameter für die Methode open als auch als Header festzulegen.

else if (/chrome/i.test(window.navigator.userAgent)) {
    fetch(url401, {
      credentials: 'include',
      headers: {
        'Authorization': 'Basic ' + btoa('none:none'),
        'X-Requested-With': 'XMLHttpRequest'
      }
    }).then(() => {
      window.location.assign(url);
    }).catch(err => console.error(err));
}

Wir stellen eine Abrufanforderung an Seite 401 mit offensichtlich falschem Benutzernamen / Passwort, wir erhalten eine 401-Antwort vom Server, der Browser leert seinen Cache.

WICHTIG! Der Server sollte KEINEN WWW-Authenticate- Header zurückgeben . Andernfalls übernimmt der Browser die Kontrolle und Weiterleitungen von Seite 401 werden niemals stattfinden. Konventionell sollte der Server diesen Header nicht zurückgeben, wenn X-Requested-With: XMLHttpRequest in der Anforderung angegeben ist . Daher wurde der Anforderung der X-Requested-With- Header hinzugefügt .

Safari (12)


Bei Safari ist die Situation genau umgekehrt: XMLHttpRequest funktioniert, aber das Abrufen funktioniert nicht

else {
    const xhr = new XMLHttpRequest();
    xhr.open("GET", url401, true, 'none', 'none');
    xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
    xhr.onerror = function(err) {
      console.error(err);
    };
    xhr.onload = function () {
      window.location.assign(url);
    };
    xhr.send()
}

Die Aktionen sind die gleichen wie in Chrome, nur über XMLHttpRequest.

Sollte für Versionen von Safari 6+ funktionieren. Frühere Versionen hatten ihre eigenen Fehler. Insbesondere in Versionen ab 5.1 hat der Browser beispielsweise bei jeder Weiterleitung die Autorisierung zwangsweise erneut angefordert, weshalb die Autorisierung mit Umleitung auf die letzte Seite im Prinzip nicht funktioniert hat. In Versionen vor 5.0 funktionierte die Protokollierung nicht.

All Articles