Как браузер знает, когда предложить пользователю сохранить пароль?

Это связано с вопросом, который я задал здесь: Как я могу заставить браузер запрашивать сохранение пароля?

это проблема: я не могу заставить свой браузер предложить мне сохранить пароль для сайта, который я разрабатываю. (Я говорю о панели, которая появляется иногда, когда вы отправляете форму в Firefox, в которой говорится: "помните пароль для yoursite.com? Да / не сейчас / никогда")

Это очень неприятно, потому что эта функция Firefox (и большинство других современные браузеры, которые, я надеюсь, работают аналогичным образом) кажется загадкой. Это похоже на волшебный трюк, который делает браузер, когда он смотрит на ваш код или то, что вы отправляете, или что-то еще, и если он "выглядит" как форма входа с полем имени пользователя (или адреса электронной почты) и полем пароля, он предлагает сохранить.

за исключением этого случая, когда он не предлагает моим пользователям эту опцию после того, как они используют мою форму входа, и это делает меня орехами. :-)

(Я проверил настройки Firefox-- I не сказали браузеру "никогда" для этого сайта. Это должно быть подсказкой.)

у меня вопрос

какие эвристики использует Firefox, чтобы знать, когда он должен предложить пользователю сохранить? Это не должно быть слишком сложно ответить, так как это прямо в источник Мозилла (я не знаю, где искать, иначе я бы попытался выкопать его сам). Мне также не повезло найти сообщение в блоге или другую подобную заметку разработчика от разработчиков Mozilla о этот.

(Я был бы в порядке с ответом на этот вопрос для Safari или IE; я бы предположил, что все браузеры очень похожи на правила, поэтому, если я могу заставить его работать в одном из них, он будет работать в других.)

(* обратите внимание, что если ваш ответ Мне имеет какое-либо отношение к cookies, шифрованию или чему-либо еще, что касается того, как я храню пароли в своей локальной базе данных, велики шансы, что вы неправильно поняли мой вопрос. :-)

13 ответов


основываясь на том, что я прочитал, я думаю, что Firefox обнаруживает пароли form.elements[n].type == "password" (итерация по всем элементам формы) , а затем обнаруживает поле имени пользователя путем поиска назад через элементы формы для текстового поля непосредственно перед полем пароля (подробнее здесь). Вы можете попробовать что-то подобное в Javascript и посмотреть, сможете ли вы обнаружить поле пароля.

из того, что я могу сказать, ваша форма входа в систему должна быть частью <form> или Firefox не обнаружит он. Настройка id="password" в поле пароля, вероятно, тоже не повредит.

Если это все еще дает вам много проблем, я бы рекомендовал спросить в одном из списков рассылки разработчиков Mozilla project (вы даже можете получить ответ от разработчика, который разработал эту функцию).


У меня была такая же проблема и я нашел решение:

  1. чтобы браузер попросил сохранить пароль, поля Имя пользователя и пароль должны быть в форме, и эта форма должна быть фактически отправлена. Кнопка отправки может возвращать false из обработчика onclick (поэтому отправка фактически не происходит).

  2. чтобы браузер восстановил ранее сохраненный пароль, поля ввода должны существовать в основной HTML-форме и не создаваться через javascript динамически. Форма может быть создана с помощью display: none.

необходимо отметить, что пароль заполняется сразу после загрузки страницы и присутствует там в течение всего сеанса, поэтому его можно прочитать с помощью введенного javascript: это делает такие атаки намного хуже. Чтобы этого избежать, переадресация на отдельную страницу просто для входа в систему разумна, и она решает все проблемы, для которых вы начали читать эту тему :). Как частичное решение I clear поля при отправке формы-если пользователь выходит из системы и хочет войти снова, пароль не заполняется браузером, но это для меня незначительно.

Вильям



вы должны посмотреть Отладка Менеджера Паролей Mozilla страница и документы nsILoginManager для авторов расширений (только для мелких технических деталей того, как Firefox занимается управлением паролями). Вы можете покопаться в ответах там и другие страницы, связанные там, чтобы узнать больше, чем вы, вероятно, когда-либо хотели знать, как менеджер паролей взаимодействует с сайтами и расширениями.

(в частности, как указано в пароле менеджер отладки doc, убедитесь, что у вас нет автозаполнения в вашем html, так как это подавит приглашение сохранить имя пользователя и пароль)


это, кажется, работает для Firefox, Chrome и Safari на Mac. Не проверено на Windows.

<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>

это необходимо добавить на страницу. Его нельзя добавить динамически. Форма и iframe могут быть настроены на отображение: нет. Если вы не установите src iframe, приглашение не будет отображаться, пока вы не отправите форму хотя бы один раз.

затем вызовите форму submit ():

bridgeForm.submit();

действие может быть необязательным, а автозаполнение может быть необязательным. Не проверял.

Примечание: в некоторых браузерах форма должна быть запущена на сервере (не localhost и не в файловой системе), прежде чем браузер ответит.

значит так:

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

не так:

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


работает для меня с angular, chrome, firefox: (я искал и тестировал часами-для chrome параметр действия формы (#) был ответ. @1.21 гигаватт, спасибо!!! Ваш ответ была неоценима.)

форма

firefox 30.0-не нуждается в скрытой кнопке iframe и submit (как показано ниже), но нуждается в директиве "login-form-autofill-fix" для распознавания автозаполненных учетных записей, как следует:

<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>

скрытый iframe

chrome 35.0-не нуждается в вышеуказанной директиве, но нуждается в скрытом iframe и кнопке отправки в реальной форме. Скрытый iframe выглядит как

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

угловая директива (с использованием jqLite)

это работает с угловым 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);
});
  • после некоторого тестирования я понял, что chrome нуждается в небольшом таймауте методом углового входа (200ms) - it кажется, перенаправление иногда слишком быстро для менеджера паролей.
  • лучше очистить browsercache... с каждым изменением

ну, на наш сайт, поле формы с именем "Имя пользователя" введите " текст "сразу за полем с именем" пароль "и введите" пароль", кажется, делает трюк.


Если вы используете AJAX login, взгляните на этот исходный код:https://gist.github.com/968927

Он состоит из отправки формы входа в скрытый iframe, так что IE и Chrome могут обнаружить фактический вход в систему, без необходимости перезагрузки страницы.


Я также заметил, что Chrome не предложит запомнить пароль, если форма входа все еще присутствует после запроса на вход, даже если она скрыта на странице.

Я думаю, он думает, что действие входа в систему не удалось и поэтому отказывается хранить недопустимые учетные данные.

видно на Chrome 34.0.


эвристика здесь довольно проста: обнаруживать поля с определенными именами в определенном порядке. Какие из них, я не могу сказать, но это отлично сработало для меня в Chrome и IE:

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.

Я бы рекомендовал смотреть на!--4-->исходный код Firefox. На самом деле это довольно простой код.

методы, которые вы хотите посмотреть на это _onFormSubmit, _getFormFields и _getPasswordFields.

возможно, вы даже найдете проблему, с которой вы столкнулись, это нераскрытая ошибка в Firefox;)https://bugzilla.mozilla.org/show_bug.cgi?id=1211780


Если у вас есть, например, два типа=текст в форме перед вводом типа=пароль, Браузер обнаруживает ближайший тип ввода=текст для вашего имени пользователя.

Это не имеет значения, другой вход имеет is=username и name=username

для решения этой проблемы вы должны ввести имя пользователя, которое вы хотите сохранить точно перед вводом пароля

Удачи :-)


в дополнение к тому, что уже было сказано, я понял, что поля ввода не должны быть "отключены". У нас был многоступенчатый логин, который сначала запрашивает имя пользователя, а затем, на следующем экране, пароль. На этом втором экране мы повторили электронное письмо, но отключили его, и это предотвратило Chrome et. Эл. от признания в качестве допустимого поля для имени пользователя.

Так как мы действительно хотели сохранить это отключенное поле ввода, мы закончили с этим hacky решение:

<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">

Я бы не пошел так далеко, чтобы рекомендовать это, но, возможно, он указывает кому-то на что-то в своем собственном коде:

  1. первый элемент отображает имя пользователя в отключенном поле ввода. Disabled не отправляет как часть формы, а disabled не распознается браузером.
  2. второй элемент является правильным полем ввода, с типом = " text "и name/id = "username". Это распознается браузером. Чтобы предотвратить пользователя от редактирования мы скрываем его с помощью CSS (display:none).

ключевое слово major находится здесь,

   <input type="password">