Woher weiß der Browser, wann er den Benutzer zum Speichern des Kennworts auffordern muss?

82

Dies hängt mit der Frage zusammen, die ich hier gestellt habe: Wie kann ich den Browser dazu bringen, zum Speichern des Passworts aufzufordern?

Dies ist das Problem: Ich kann meinen Browser nicht dazu bringen, mich aufzufordern, das Passwort für die Site zu speichern, die ich entwickle. (Ich spreche von der Leiste, die manchmal angezeigt wird, wenn Sie ein Formular in Firefox senden, in dem steht: "Erinnern Sie sich an das Passwort für Ihre Website.com? Ja / Nicht jetzt / Nie")

Dies ist sehr frustrierend, da diese Funktion von Firefox (und den meisten anderen modernen Browsern, von denen ich hoffe, dass sie auf ähnliche Weise funktionieren) ein Rätsel zu sein scheint. Es ist wie ein Zaubertrick, den der Browser ausführt, wenn er Ihren Code oder das, was Sie übermitteln, oder etwas anderes betrachtet, und wenn er wie ein Anmeldeformular mit einem Feld für Benutzername (oder E-Mail-Adresse) und einem Passwortfeld "aussieht", bietet er speichern.

Außer in diesem Fall, wo es meinen Benutzern diese Option nicht bietet, nachdem sie mein Anmeldeformular verwendet haben, und es mich verrückt macht. :-)

(Ich habe meine Firefox-Einstellungen überprüft. Ich habe dem Browser NICHT "nie" für diese Site mitgeteilt. Es sollte eine Aufforderung sein.)

Meine Frage

Welche Heuristiken verwendet Firefox, um zu wissen, wann der Benutzer zum Speichern aufgefordert werden soll? Dies sollte nicht allzu schwer zu beantworten sein, da es genau dort in der Mozilla-Quelle steht (ich weiß nicht, wo ich suchen soll, sonst würde ich versuchen, es selbst herauszufinden). Ich hatte auch kein Glück, einen Blog-Beitrag oder einen ähnlichen Entwickler-Hinweis der Mozilla-Entwickler dazu zu finden.

(Es wäre in Ordnung, wenn diese Frage für Safari oder IE beantwortet würde. Ich würde mir vorstellen, dass alle Browser sehr ähnliche Regeln verwenden. Wenn ich sie also in einem von ihnen zum Laufen bringen kann, funktioniert sie in den anderen.)

(* Beachten Sie, dass wenn Ihre Antwort an mich etwas mit Cookies, Verschlüsselung oder irgendetwas anderem zu tun hat, bei dem es darum geht, wie ich Passwörter in meiner lokalen Datenbank speichere, die Wahrscheinlichkeit groß ist, dass Sie meine Frage falsch verstanden haben. :-)

Eric
quelle
1
Ich weiß nicht. Ist Ihr Formular ein POST-Formular mit einem Passwortfeld?
Zneak
2
Ja, in <form> -Tags eingeschlossen, und die Felder heißen 'Benutzername' und 'Passwort'. Ich lade es als separate Ebene mit AJAX, aber auch disqus.com (nur um ein Beispiel herauszubringen) und es funktioniert großartig für sie. Aus diesem Grund möchte ich, anstatt die Dinge nach dem Zufallsprinzip zu optimieren, um festzustellen, ob sie irgendwie helfen, genau herausfinden, wie der Browser denkt.
Eric

Antworten:

55

Basierend auf dem, was ich gelesen habe, erkennt Firefox Passwörter durch form.elements[n].type == "password"(Durchlaufen aller Formularelemente) und erkennt dann das Benutzernamenfeld, indem es Formularelemente unmittelbar vor dem Passwortfeld rückwärts in Formularelementen nach dem Textfeld durchsucht (weitere Informationen hier ). Sie können etwas Ähnliches in Javascript versuchen und prüfen, ob Sie Ihr Kennwortfeld erkennen können.

Nach allem, was ich sagen kann, muss Ihr Anmeldeformular Teil eines sein, <form>oder Firefox erkennt es nicht. Das Einstellen id="password"in Ihrem Passwortfeld kann wahrscheinlich auch nicht schaden.

Wenn dies immer noch viele Probleme verursacht, würde ich empfehlen, auf einer der Entwickler-Mailinglisten des Mozilla-Projekts nachzufragen (möglicherweise erhalten Sie sogar eine Antwort von dem Entwickler, der die Funktion entwickelt hat).

bta
quelle
2
Das ist wunderbar. Vielen Dank. Das suche ich.
Eric
1
Dies hat mir geholfen, es in Firefox zum Laufen zu bringen, aber ich habe kein Glück mit Chrome. Dies ist das Formular, das ich verwende: <form id = "myForm" action = "#"> <input id = "username"> <input id = "password" type = "password"> </ form>
1,21 Gigawatt
3
@ 1.21gigawatts- Es gibt keine "Standard" -Methode, um dies zu tun (meines Wissens), so dass verschiedene Browser dies möglicherweise etwas anders machen. Ich weiß nicht, wie sich der Prozess von Chrome von dem von Firefox unterscheidet, aber Sie können es möglicherweise herausfinden, wenn Sie den Chrome-Quellcode durchsehen. Ich wusste nur, wie Firefox es tat, indem ich ihren Code las. Dies ist die Art von Dingen, die jemand in einem großen Diagramm dokumentieren muss, in dem aufgeführt ist, wie jeder Browser dies tut ...
bta
3
Ein Autor des Passwort - Manager Code führt Sie durch die Dinge in einem Blog - Post 2013 - es ist eine lohnende Lektüre: blog.mozilla.org/dolske/2013/08/20/on-firefoxs-password-manager
dat
2
Aktualisierter Link zu den Blog-Posts des Passwort-Managers: dolske.wordpress.com/2013/08
Vsevolod Golovanov
17

Ich hatte das gleiche Problem und fand eine Lösung:

  1. Damit der Browser nach dem Speichern des Passworts fragt, müssen die Felder für Benutzername und Passwort in einem Formular vorliegen und dieses Formular muss tatsächlich gesendet werden. Die Schaltfläche "Senden" kann vom Onclick-Handler "false" zurückgeben (das Senden erfolgt also nicht tatsächlich).

  2. Damit der Browser das zuvor gespeicherte Kennwort wiederherstellt, müssen die Eingabefelder im HTML-Hauptformular vorhanden sein und dürfen nicht dynamisch über Javascript erstellt werden. Das Formular kann mit Anzeige erstellt werden: keine.

Es ist zu beachten, dass das Passwort sofort nach dem Laden der Seite ausgefüllt wird und dort während der gesamten Sitzung vorhanden ist, damit es durch injiziertes Javascript gelesen werden kann: Es verschlimmert solche Angriffe erheblich. Um dies zu vermeiden, ist es sinnvoll, nur zum Anmelden auf eine separate Seite weiterzuleiten, und es löst alle Probleme, für die Sie dieses Thema gelesen haben :). Als Teillösung lösche ich die Felder beim Absenden des Formulars - wenn sich der Benutzer abmeldet und sich erneut anmelden möchte, wird das Passwort nicht vom Browser ausgefüllt, aber das ist für mich unbedeutend.

Viliam


user324356
quelle
Funktioniert in Firefox 3.5 und IE8, funktioniert nicht in Chrome (Punkt 1 funktioniert nicht). Vielleicht muss die
Übermittlung
user324356 - Ich habe das Formular auf "#" gesetzt und dann myForm.submit () aufgerufen. Das hat in Firefox funktioniert, aber nicht in Chrome.
1,21 Gigawatt
1
fyi: Wenn Sie verwenden return falseoder event.preventDefault()dies wird in Chrome wegen dieses Fehlers nicht funktionieren: code.google.com/p/chromium/issues/detail?id=282488
mkurz
Dies ist definitiv wichtig für den aktuellen Algorithmus, der von Firefox verwendet wird - es ist nicht das einzige, wonach der Passwort-Manager "sucht", aber der Firefox-Passwort-Manager wird ohne tatsächliche Übermittlung nicht ausgelöst.
dat
Update: Chrome 46 hat sein falsches Verhalten behoben - jetzt sollte alles gut funktionieren. Siehe stackoverflow.com/a/33113374/810109
mkurz
10

Sie sollten sich die Debugging- Seite von Mozilla Password Manager und die nsILoginManager-Dokumente für Erweiterungsschreiber ansehen (nur die wichtigsten technischen Details zum Umgang von Firefox mit der Kennwortverwaltung). Sie können die Antworten dort und andere dort verlinkte Seiten durchsuchen, um mehr zu erfahren, als Sie wahrscheinlich jemals wissen wollten, wie der Passwort-Manager mit Websites und Erweiterungen interagiert.

(Stellen Sie insbesondere, wie im Debugging-Dokument für den Kennwortmanager angegeben, sicher, dass die automatische Vervollständigung in Ihrem HTML nicht deaktiviert ist, da dies die Aufforderung zum Speichern des Benutzernamens und des Kennworts unterdrückt.)

Nick Bastin
quelle
7

Dies scheint für Firefox, Chrome und Safari auf dem Mac zu funktionieren. Nicht unter Windows getestet.

<form id="bridgeForm" action="#" target="loginframe" autocomplete="on">
    <input type="text" name="username" id="username" />
    <input type="password" name="password" id="password"/>
</form>

<iframe id="loginframe" name="loginframe" src="anyblankpage.html"></iframe>

Dies muss der Seite hinzugefügt werden. Es kann nicht dynamisch hinzugefügt werden. Das Formular und der Iframe können so eingestellt werden, dass Folgendes angezeigt wird: keine. Wenn Sie den Quellcode des Iframes nicht festlegen, wird die Eingabeaufforderung erst angezeigt, wenn Sie das Formular mindestens einmal gesendet haben.

Rufen Sie dann das Formular submit () auf:

bridgeForm.submit();

Die Aktion kann optional sein und die automatische Vervollständigung kann optional sein. Nicht getestet.

Hinweis : In einigen Browsern muss das Formular auf einem Server (nicht localhost und nicht im Dateisystem) ausgeführt werden, bevor der Browser antwortet.

Also das:

http://www.mysite.com/myPage.html

nicht das:

http://126.0.0.1/myPage.html
http://localhost/myPage.html
file://directory/myPage.html

1,21 Gigawatt
quelle
@ErikAronesty hast du eine lösung gefunden? Ich habe festgestellt, dass sich die Seite in einigen Browsern (Safari) auf einem Server befinden muss und nicht auf einem lokalen Host oder dem Dateisystem.
1,21 Gigawatt
1
Chrome 46 hat sein falsches Verhalten behoben - es sind keine iframeProblemumgehungen mehr erforderlich. Siehe stackoverflow.com/a/33113374/810109
mkurz
6

Funktioniert für mich mit Angular, Chrome, Firefox: (Ich habe stundenlang gesucht und getestet - für Chrome war der Formularaktionsparameter ( #) die Antwort. @ 1,21 Gigawatt , danke !!! Ihre Antwort war von unschätzbarem Wert.)

bilden

Firefox 30.0 - benötigt keinen versteckten Iframe- und Submit-Button (wie unten gezeigt), sondern die Anweisung "Login-Form-Autofill-Fix" zum Erkennen der automatisch ausgefüllten Anmeldeinformationen wie folgt:

<form name="loginForm" login-form-autofill-fix action="#" target="emptyPageForLogin" method="post" ng-submit="login({loginName:grpEmail,password:grpPassword})">
<input type="text" name=username" id="username" ng-model="grpEmail"/>
<input type="password" name="password" id="password" ng-model="grpPassword"/>
<button type="submit">Login</button>
</form>

versteckter Iframe

chrome 35.0 - benötigt die obige Direktive nicht, benötigt aber einen versteckten iframe und einen Submit-Button im realen Formular. Der versteckte Iframe sieht aus wie

<iframe src="emptyPageForLogin.html" id="emptyPageForLogin" name="emptyPageForLogin" style="display:none"></iframe>

Winkelanweisung (mit jqLite)

Dies funktioniert mit Winkel 1.2.18

module.directive('loginFormAutofillFix', function() { 
            return function(scope, elem, attrs) {
        if(!attrs.ngSubmit) {
            return;
        }
        setTimeout(function() {
            elem.unbind("submit").bind("submit", function(e) {
                //DO NOT PREVENT!  e.preventDefault(); 
                elem.find("input").triggerHandler("input");
                scope.$apply(attrs.ngSubmit);
            });
        }, 0);
});

Änderung

  • Nach einigen Tests wurde mir klar, dass Chrome durch die Winkel-Anmeldemethode (200 ms) eine kleine Zeitüberschreitung benötigt - anscheinend ist die Umleitung für den Passwort-Manager manchmal einfach zu schnell.
  • Browser-Cache besser löschen ... bei jeder Änderung
110maor
quelle
seit neuestem chrom füllt der pw-manager das formular nur manchmal aus. auch der pw manager taucht manchmal auf, manchmal nicht ... scheint jetzt eine zufällige Funktion zu sein.
110maor
Der neue Firefox ignoriert das automatisch ausgefüllte Kennwortfeld. Der TriggerHandler ("Eingabe") funktioniert nicht. Dies kann mit einem nativen Ereignis (document.createEvent) gelöst werden - senden Sie ihm ein Feuer.
110maor
1
Chrome 46 hat sein falsches Verhalten behoben - es sind keine iframeProblemumgehungen mehr erforderlich. Siehe stackoverflow.com/a/33113374/810109
mkurz
@ 110maor Ich habe lange gebraucht, um deinen Beitrag zu verstehen. Ich hoffe, meine Änderungen entsprechen Ihrer Absicht.
Jpaugh
3

Nun, auf unserer Website scheint ein Formularfeld mit dem Namen "Benutzername" Typ "Text" unmittelbar gefolgt von einem Feld mit dem Namen "Passwort" und dem Typ "Passwort" den Trick zu tun.

Spender
quelle
Zu schnell für mich! Meine Gedanken genau ... (Ich lösche meine Antwort)
Ganesh Shankar
Ja. Ich habe es versucht. Kein Glück. :-( Meine Theorie ist, dass ich etwas anderes auf der Seite habe, das der Browser nicht mag / denkt, dass die Seite kein Anmeldeformular hat ...
Eric
3

Wenn Sie die AJAX-Anmeldung verwenden, sehen Sie sich den Quellcode an: https://gist.github.com/968927

Es besteht darin, ein Anmeldeformular an einen versteckten Iframe zu senden, damit IE und Chrome die tatsächliche Anmeldung erkennen können, ohne die Seite neu laden zu müssen.

Adrien Joly
quelle
Chrome 46 hat sein falsches Verhalten behoben - es sind keine iframeProblemumgehungen mehr erforderlich. Siehe stackoverflow.com/a/33113374/810109
mkurz
3

Die Heuristiken sind hier ziemlich einfach: Erkennen Sie Felder mit bestimmten Namen in einer bestimmten Reihenfolge. Welche kann ich nicht sagen, aber das hat in Chrome und IE gut funktioniert:

Username field: name "login", type "text";
Password field: name "password", type "password"
Submit button: element "input", type "submit". 
Element "button" type "submit" did not work.
user19878
quelle
Ich hatte zu ersetzen <button type="submit">durch <input type="submit">Dashlane zur Arbeit zu kommen. Ich kann nicht glauben, dass dies überhaupt eine Sache ist ...
Bram Verstraten
3

Ich habe auch festgestellt, dass Chrome nicht anbietet, sich ein Passwort zu merken, wenn das Anmeldeformular nach der Anmeldeanforderung noch vorhanden ist, selbst wenn es auf der Seite ausgeblendet ist.

Ich denke, es glaubt, dass die Anmeldeaktion fehlgeschlagen ist und sich daher weigert, ungültige Anmeldeinformationen zu speichern.

Gesehen auf Chrome 34.0.

ZeWaren
quelle
1
Chrome 46 hat sein falsches Verhalten behoben. Das Ausblenden des Formulars nach einer Ajax-Anfrage sollte ausreichen. Siehe stackoverflow.com/a/33113374/810109
mkurz
0

Zusätzlich zu vielem, was bereits gesagt wurde, wurde mir klar, dass die Eingabefelder nicht "deaktiviert" werden dürfen. Wir hatten eine mehrstufige Anmeldung, bei der zuerst nach dem Benutzernamen und dann im nächsten Bildschirm nach dem Passwort gefragt wurde. Auf diesem zweiten Bildschirm haben wir die E-Mail wiederholt, aber deaktiviert, was Chrome et. al. von der Erkennung als gültiges Feld für den Benutzernamen.

Da wir dieses deaktivierte Eingabefeld wirklich beibehalten wollten, haben wir diese hackige Problemumgehung erhalten:

<input type="text" name="display-username" id="display-username" value="ENTERED_USERNAME" placeholder="Username" disabled="disabled">
<input type="text" name="username" id="username" value="ENTERED_USERNAME" placeholder="Username" style="display: none;">
<input type="password" name="password" id="password" value="" autofocus="autofocus" autocomplete="on" placeholder="Password" required="required">

Ich würde nicht so weit gehen, um dies zu empfehlen, aber vielleicht weist es jemanden auf etwas in seinem eigenen Code hin:

  1. Das erste Element zeigt den Benutzernamen in einem deaktivierten Eingabefeld an. Deaktiviert wird nicht als Teil des Formulars gesendet und deaktiviert wird vom Browser nicht erkannt.
  2. Das zweite Element ist ein richtiges Eingabefeld mit type = "text" und name / id = "username". Dies wird vom Browser erkannt. Um zu verhindern, dass der Benutzer es bearbeitet, verstecken wir es mit CSS (Anzeige: keine).
hendrikbeck
quelle
In Situationen, in denen Sie eine Eingabe wünschen, deren Wert übermittelt wird, die der Benutzer jedoch nicht ändern kann, möchten Sie möglicherweise "schreibgeschützt" anstelle von "deaktiviert" versuchen.
David Brown
0

Wenn Sie vor der Eingabe von type = password beispielsweise zwei type = text in Ihrem Formular haben, erkennt der Browser den nächsten input type = text für Ihren Benutzernamen.

Dies spielt keine Rolle, wenn eine andere Eingabe = Benutzername und Name = Benutzername lautet

Um dieses Problem zu lösen, müssen Sie Ihren Benutzernamen, den Sie speichern möchten, genau vor Ihrem Eingabekennwort eingeben

Viel Glück :-)

keivan kashani
quelle
-2

Das Hauptschlüsselwort ist hier,

   <input type="password">
Jeba Moses
quelle
1
Versuchen Sie, Ihre Antwort mit einigen weiteren Details zu erklären, da dies für andere hilfreich sein wird.
Ashish Duklan