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

82

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

Это проблема: я НЕ МОГУ заставить свой браузер предлагать мне сохранить пароль для сайта, который я разрабатываю. (Я говорю о панели, которая иногда появляется, когда вы отправляете форму в Firefox, которая говорит: «Запомнить пароль для yoursite.com? Да / Не сейчас / Никогда»)

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

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

(Я проверил свои настройки Firefox - я НЕ сказал браузеру «никогда» для этого сайта. Он должен выдавать запрос.)

Мой вопрос

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

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

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

Эрик
источник
1
Понятия не имею. Является ли ваша форма POST-формой с полем для ввода пароля?
zneak 08
2
Да, заключены в теги <form>, а поля названы «имя пользователя» и «пароль». Я загружаю его как отдельный слой с AJAX, но также и disqus.com (просто чтобы показать пример), и он отлично работает для них. Вот почему вместо того, чтобы (продолжать) произвольно настраивать вещи, чтобы увидеть, помогает ли это каким-то образом, я хочу точно узнать, как думает браузер.
Эрик

Ответы:

55

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

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

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

bta
источник
2
Это прекрасно. Благодарю. Вот что я ищу.
Эрик
1
Это помогло мне заставить его работать в Firefox, но мне не везет с Chrome. Я использую следующую форму: <form id = "myForm" action = "#"> <input id = "username"> <input id = "password" type = "password"> </form>
1,21 гигаватт
3
@ 1.21gigawatts - Нет "стандартного" способа сделать это (насколько мне известно), поэтому разные браузеры могут делать это немного по-разному. Я не знаю, чем процесс Chrome отличается от Firefox, но вы можете понять это, если просмотрите исходный код Chrome. Единственный способ узнать, как работает Firefox, - это прочитать их код. Это то, что кому-то нужно задокументировать в большой диаграмме, перечисляя, как это делает каждый браузер ...
bta
3
Автор кода диспетчера паролей проведет вас через все в своем сообщении в блоге 2013 года - его стоит прочитать: blog.mozilla.org/dolske/2013/08/20/on-firefoxs-password-manager
dat
2
Обновлена ​​ссылка на сообщения в блоге о менеджере паролей: dolske.wordpress.com/2013/08
Всеволод Голованов,
17

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

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

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

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

Вильям


user324356
источник
Работает в Firefox 3.5 и IE8, не работает в Chrome (пункт 1 не работает). Может быть,
отправка
user324356 - Я установил для формы значение «#», затем вызвал myForm.submit (), и это сработало в Firefox, но не в Chrome.
1,21 гигаватт
1
к сведению: когда вы используете return falseили event.preventDefault()это не будет работать в Chrome из-за этой ошибки: code.google.com/p/chromium/issues/detail?id=282488
mkurz
Это определенно важно для текущего алгоритма, используемого firefox - это не единственное, что менеджер паролей «ищет», но менеджер паролей firefox не будет запущен без фактической отправки.
дата
Обновление: в Chrome 46 исправлено неправильное поведение - теперь все должно работать нормально. См stackoverflow.com/a/33113374/810109
mkurz
10

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

(В частности, как указано в отладочной документации диспетчера паролей, убедитесь, что в вашем html не отключено автозаполнение, так как это подавит запрос на сохранение имени пользователя и пароля)

Ник Бастин
источник
7

Кажется, это работает для 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();

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

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

Итак, это:

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

не этот:

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

1,21 гигаватт
источник
@ErikAronesty вы придумали решение? Я заметил, что в некоторых браузерах (сафари) страница должна находиться на сервере, а не на локальном хосте или в файловой системе.
1,21 гигаватт
1
В Chrome 46 исправлено неправильное поведение - iframeобходных путей больше не требуется. См stackoverflow.com/a/33113374/810109
mkurz
6

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

форма

firefox 30.0 - не требуется скрытый iframe и кнопка отправки (как показано ниже), но требуется директива "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)

Это работает с angular 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 требует небольшого тайм-аута с помощью метода входа angular (200 мс) - кажется, перенаправление иногда бывает слишком быстрым для менеджера паролей.
  • лучше очищать кеш браузера ... при каждом изменении
110maor
источник
начиная с новейшего хрома, pw-менеджер лишь иногда заполняет форму. также менеджер pw иногда всплывает, иногда нет ... теперь кажется, что это случайная функция.
110maor 01
новый Firefox игнорирует автоматически заполняемое поле пароля. triggerHandler ("input") не работает. это можно решить с помощью собственного события (document.createEvent) - отправить его в огонь.
110maor 01
1
В Chrome 46 исправлено неправильное поведение - iframeобходных путей больше не требуется. См stackoverflow.com/a/33113374/810109
mkurz
@ 110maor Мне потребовалось много времени, чтобы понять ваш пост. Надеюсь, мои правки соответствуют вашим намерениям.
jpaugh
3

Что ж, на нашем сайте поле формы с именем «имя пользователя» типа «текст», сразу за которым следует поле с именем «пароль» и типом «пароль», похоже, помогает.

расточитель
источник
Слишком быстро для меня! Мои мысли точно ... (я удаляю свой ответ)
Ганеш Шанкар
Да. Пробовал. Неудачно. :-( Моя теория заключается в том, что у меня на странице есть что-то еще, что браузеру не нравится / заставляет его думать, что на странице нет формы для входа ...
Эрик
3

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

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

Адриен Джоли
источник
В Chrome 46 исправлено неправильное поведение - iframeобходных путей больше не требуется. См stackoverflow.com/a/33113374/810109
mkurz
3

Эвристика здесь довольно проста: обнаружение полей с определенными именами в определенном порядке. Какие, я не могу сказать, но у меня это отлично сработало в 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.
user19878
источник
Мне пришлось заменить <button type="submit">на, <input type="submit">чтобы Dashlane заработал. Не могу поверить, что это вообще вещь ...
Брэм Верстратен
3

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

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

Встречается в Chrome 34.0.

ZeWaren
источник
1
В Chrome 46 исправлено неправильное поведение, достаточно было скрыть форму после запроса ajax. См stackoverflow.com/a/33113374/810109
mkurz
3

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

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

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

WoodenKitty
источник
0

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

Поскольку мы действительно хотели сохранить отключенное поле ввода, мы пришли к следующему обходному пути:

<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. Первый элемент отображает имя пользователя в отключенном поле ввода. Отключено не отправляется как часть формы, а отключенное не распознается браузером.
  2. Второй элемент - это правильное поле ввода с type = "text" и name / id = "username". Это распознается браузером. Чтобы пользователь не мог его редактировать, мы скрываем его с помощью CSS (display: none).
Хендрикбек
источник
В ситуациях, когда вам нужен ввод, значение которого отправлено, но которое пользователь не может изменить, вы можете попробовать «только для чтения» вместо «отключено».
Дэвид Браун
0

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

Это не имеет значения, что другой вход имеет = имя пользователя и имя = имя пользователя

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

Удачи :-)

Кейван Кашани
источник
-2

Главное ключевое слово здесь,

   <input type="password">
Джеба Моисей
источник
1
Попытайтесь объяснить свой ответ более подробно, так как это будет полезно другим.
Ашиш Дуклан