Автозаполнение / автозаполнение Chrome без пароля

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

Если вы нажмете где-то на странице не важно, где значение input type="password" будет заполнено.

Это Fiddle пользователь / проход структуры HTML и console.log команда. Его нельзя увидеть здесь, но его можно воспроизвести на каждой странице, которая имеет форму входа, а имя пользователя и пароль автоматически заполняются при загрузке страницы. Если вы проверите значение поля перед тем, как щелкнуть где-либо еще на сайте, это будет пустая строка.

Это не так в Firefox или Internet Explorer, он будет заполнять значение input элемент с паролем.

Я использую 64-битную ОС Windows 7 Ultimate, а версия Google Chrome составляет 48.0.2564.97 м.

Это нормальное поведение, ошибка или?

ОБНОВИТЬ:

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

23 ответа

Решение

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

На самом деле я не уверен на 100%, является ли это ошибкой или есть причина безопасности, например, предотвращение кражи вашего пароля скрытым фреймом путем обмана браузера для его заполнения.

Обходной путь, который мы использовали, заключается в обнаружении изменения цвета фона, которое Chrome вносит в поля, которые он автоматически заполняет. Хром окрашивает фон автоматически заполненных полей в желтый, и это изменение всегда видно в Javascript, даже если это значение отсутствует. Обнаружение этого в Javascript позволяет нам знать, что поле было автоматически заполнено значением, даже если мы видим значение пустым в Javascript. В нашем случае у нас есть форма входа в систему, в которой кнопка отправки не активна, пока вы не введете что-либо в поле пароля, и определение либо значения, либо цвета автозаполнения достаточно для определения того, что что-то находится в поле, Затем мы можем активировать кнопку отправки, и нажатие кнопки (или нажатие кнопки ввода) мгновенно делает значение поля пароля видимым для Javascript, потому что взаимодействие со страницей устраняет проблему, поэтому мы можем продолжить работу с этого момента.

Рабочий ответ от 8 июля 2016 г.

Адам правильно заявил, что это ошибка (или предполагаемое поведение). Однако ни в одном из предыдущих ответов на самом деле не говорится, как это исправить, поэтому здесь приведен метод, который заставляет Chrome обрабатывать значение автозаполнения как реальное значение.

Несколько вещей должны произойти по порядку, и это должно работать только в Chrome, а не Firefox, следовательно, if,

Сначала мы сосредоточимся на элементе. Затем мы создаем новый TextEventи запустить initTextEvent, который добавляет пользовательскую строку, которую мы указываем (я использовал "@@@@@") к началу значения. Это приводит к тому, что Chrome начинает действовать, как будто значение реально. Затем мы можем удалить пользовательскую строку, которую мы добавили, и затем мы расфокусируемся.


Код:

input.focus();

var event = document.createEvent('TextEvent');

if ( event.initTextEvent ) {

    event.initTextEvent('textInput', true, true, window, '@@@@@');

    input.dispatchEvent(event);

    input.value = input.value.replace('@@@@@','');

}

input.blur();

Редактировать 10 августа 2016 г.

Это работает только сейчас в Chrome на Windows и Android. Не работает на OSX. Кроме того, он вообще перестанет работать в сентябре 2016 года, согласно:

https://www.chromestatus.com/features/5718803933560832

Кроме того, я открыл билет Chromium.

https://bugs.chromium.org/p/chromium/issues/detail?id=636425

По состоянию на 12 августа один из членов команды Chrome сказал, что поведение не изменится, потому что они не считают это ошибкой.

Долгосрочное предложение для обходного пути:

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


Изменить 13 декабря 2016 года:

Новый билет Chromium был открыт и принимается лучше. Если вы хотите изменить это поведение Chrome, отметьте этот новый билет:

https://bugs.chromium.org/p/chromium/issues/detail?id=669724

Продолжая то, что сказал Энди Мерсер, вот моя работа вокруг. Как и многим людям, мне не нужно фактическое значение пароля. Мне просто нужно знать, что поле пароля было заполнено автоматически, чтобы я мог отображать правильные сообщения проверки.

Лично я бы не использовал предложенное решение для определения причины изменения цвета фона при автозаполнении Chrome. Такой подход кажется хрупким. Это зависит от того, что желтый цвет никогда не меняется. Но это может быть изменено расширением и может быть другим в другом браузере на базе Blink (например, Opera). Кроме того, нет никаких обещаний, что Google не будет использовать другой цвет в будущем. Мой метод работает независимо от стиля.

Во-первых, в CSS я устанавливаю содержимое INPUT когда -webkit-autofil К нему применяется псевдокласс:

input:-webkit-autofill {
  content: "\feff"
}

Затем я создал процедуру проверки содержимого, которое нужно установить:

const autofillContent = `"${String.fromCharCode(0xFEFF)}"`;
function checkAutofill(input) {
    if (!input.value) {
        const style = window.getComputedStyle(input);
        if (style.content !== autofillContent)
            return false;
    }

    //the autofill was detected
    input.classList.add('valid'); //replace this. do want you want to the input
    return true;
}

Наконец, я опросил input чтобы время автозаполнения завершилось:

const input = document.querySelector("input[type=password]");

if (!checkAutofill(input)) {
    let interval = 0;
    const intervalId = setInterval(() => {
        if (checkAutofill(input) || interval++ >= 20)
            clearInterval(intervalId);
    }, 100);
}

Удивительно, что в 2021 году это еще не было решено в Chrome, у меня проблема с автозаполнением с 2014 года, и все еще ничего.

Автозаполнение функций Chrome вводит пользователя в заблуждение, я не знаю, чего они пытаются достичь, но выглядит не очень хорошо.

Как и сейчас, форма отображается с автоматически заполненным текстом (пользователь / электронная почта / пароль) для пользователя, но в фоновом формате html - значения не находятся внутри элементов. Поскольку значения не указаны в полях, пользовательская проверка отключит кнопку отправки.

Сценарий, проверяющий значения полей, скажет, что значение равно нулю, что еще больше сбивает с толку пользователя, поскольку он / она может видеть текст, и может предполагать, что он действителен, что приводит к путанице при вставке одного символа delete-one. (К сожалению, я должен признать, что не знал, что вам нужно щелкнуть в теле HTML, поэтому мне интересно, сколько пользователей не знают того же)

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

Если мы попробуем мы обнаружим, что это не работает. И чтобы проверить поля и, скажем, кнопку включения, нам нужно проделать некоторые трюки. (Имейте в виду, что я пробовал new-password) и другие уловки Hocus-Pocus с официального ресурса .

В конце концов, я сделал это.

      <script>
  $('#user').value = ' '; //one space
  $('#pass').value = ' '; // one space - if this is empty/null it will autopopulate regardless of on load event
  window.addEventListener('load', () => {
      $('#user').value = ''; // empty string
      $('#pass').value = ''; // empty string 
  });
</script>

Таким образом, в некоторых случаях он будет мигать на долю секунды в поле пароля с не идеально, но:/ ...

Вот мое решение этой проблемы:

$(document).ready(function(){
  if ( $("input:-webkit-autofill").length ){
    $(".error").text("Chrome autofill detected. Please click anywhere.");
  }
});

$(document).click(function(){
  $(".error").text("");
});

По сути, щелчок делает ввод видимым для пользователя, поэтому я прошу пользователя нажать, а когда он это делает, я скрываю сообщение.

Не самое элегантное решение, но, пожалуй, самое быстрое.

Другой вариант с 16 декабря / Chrome 54

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

setTimeout(function() {
  // get the password field
  var pwd = document.getElementById('pwd');
  pwd.focus();
  pwd.select();
  var noChars = pwd.selectionEnd;
  // move focus to username field for first-time visitors
  document.getElementById('username').focus()
  if (noChars > 0) {
    document.getElementById('loginBtn').disabled = false;
  }
}, 100);

Обходной путь, указанный Адамом:

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

Я сделал это так:

getComputedStyle(element).backgroundColor === "rgb(250, 255, 189)"

где rgb(250, 255, 189) - желтый цвет, который Chrome применяет к автоматически заполненным входам.

Просто написал угловую директиву, связанную с этим. Завершается следующим кодом:

if ('password' == $attrs.type) {
      const _interval = $interval(() => { //interval required, chrome takes some time to autofill
          if ($element.is(':-webkit-autofill')) { //jQuery.is()
              //your code
              $interval.cancel(_interval);
          }
      }, 500, 10); //0.5s, 10 times
}

PS: он не будет обнаруживать в 100% случаев, Chrome может занять более 5 секунд, чтобы заполнить ввод.

Я нашел решение этой проблемы, которое работает, по крайней мере, для моих целей.

У меня есть форма входа, которую я просто хочу нажать Enter, как только она загрузится, но я столкнулся с проблемой пустых паролей в Chrome.

Кажется, что следующее работает, позволяя исходному ключу ввода выйти из строя и повторить попытку после пробуждения Chrome и предоставления значения пароля.

$(function(){

    // bind form submit loginOnSubmit
    $('#loginForm').submit(loginOnSubmit);

    // submit form when enter pressed on username or password inputs
    $('#username,#password').keydown(function(e) {
        if (e.keyCode == 13) {
            $('#loginForm').submit(e);
            return false;
        }
    });

});

function loginOnSubmit(e, passwordRetry) {

    // on submit check if password is blank, if so run this again in 100 milliseconds
    // passwordRetry flag prevents an infinite loop
    if(password.value == "" && passwordRetry != true)
    {
        setTimeout(function(){loginOnSubmit(e,true);},100);
        return false;
    }

    // login logic here
}

Предполагаемое поведение Chrome заключается в том, что автоматически заполненный пароль имеет пустой value в DOM, пока пользователь каким-либо образом не взаимодействует с фреймом, после чего Chrome фактически заполняет значение. До этого момента любая проверка на стороне клиента или попытка ajax отправить форму будут видеть пароль пустым.

Такое поведение "заполнение пароля при взаимодействии фреймов" является непоследовательным. Я обнаружил, что когда форма размещается в iframe того же источника, она работает только при первой загрузке, а не при последующих.

Это наиболее очевидно в формах ajax, где пароль автозаполнения заполняется при первой загрузке, однако, если этот пароль недействителен, а при представлении ajax повторно отображается форма DOM, пароль автозаполнения вновь появляется визуально, но value никогда не заселен, независимо от взаимодействия.

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

$('input[type="password"]').val("");

После вышесказанного Chrome снова автоматически заполняет пароль, но с value на самом деле населенный.

В моем текущем случае использования я использую Ajax.BeginForm ASP.NET и использую вышеупомянутый обходной путь в обратном вызове AjaxOptions.OnSuccess.

$element.is("*:-webkit-autofill")

работает для меня

С Angular новое поведение в Chrome (позволяющее читать автозаполненные значения только после того, как пользователь взаимодействует со страницей) проявляется как проблема, когда вы используете функцию проверки Angular в определенных сценариях (например, при использовании стандартных атрибутов метода / действия на форме). Поскольку обработчик отправки выполняется немедленно, он не позволяет валидаторам формы получать автоматически заполненные значения из Chrome.

Решение, которое я нашел для этого, чтобы явно вызывать контроллеры форм $commitViewValue функция в обработчике отправки для запуска повторной проверки перед проверкой form.$valid или же form.invalid и т.п.

Пример:

function submit ($event) {
    // Allow model to be updated by Chrome autofill
    // @see http://stackru.com/questions/35049555/chrome-autofill-autocomplete-no-value-for-password
    $scope.loginModule.$commitViewValue();

    if ($scope.loginModule.$invalid) {
        // Disallow login
        $scope.loginModule.$submitted = true;
        $event.preventDefault();
    } else {
        // Allow login
    }
}

Пока это работает для нас, мне было бы очень интересно, если бы кто-то нашел другую, более изящную работу для решения этой проблемы.

var txtInput = $(sTxt);
txtInput.focus();
txtInput.select();

Это решение сработало в моем случае. Использование jQuery 3.1.1.

Если вы хотите, чтобы ввод был воспринят как выполненный, попробуйте вызвать blur в теме:$('input[type="password"]').blur();

Мое решение, сравнивающее мой css с цветом автозаполнения хрома...

$('input, select, textarea').each(function(){
    var inputValue = $(this).val();
    if ( inputValue != "" || $(this).css("background-color") != "rgba(255, 255, 255, 0)") {
        $(this).parents('.form-group').addClass('focused');
    }
});

Мне казалось, что ни одно из этих решений не сработало.

Я думаю, стоит упомянуть, что если вы хотите использовать его для стилизации CSS, вы должны использовать свойство -webkit-autofill следующим образом:

input:-webkit-autofill~.label,
input:-webkit-autofill:hover~.label, 
input:-webkit-autofill:focus~.label
input:focus~.label,
input:not(.empty)~.label {
  top: -12px;
  font-size: 12px;
  color: rgba(0, 0, 0, .4);
  font-weight: 600
}

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

 setTimeout(function () {
     var autofilled = document.querySelectorAll('input:-webkit-autofill');
         for (var i = 0; i < autofilled.length; i++) {
             Do something with your input autofilled
         }
 }, 200);

Функция автозаполнения успешно отключена.Оно работает!

[HTML]

<div id="login_screen" style="min-height: 45px;">
   <input id="password_1" type="text" name="password">
</div>

[JQuery]

$("#login_screen").on('keyup keydown mousedown', '#password_1', function (e) {
    let elem = $(this);

    if (elem.val().length > 0 && elem.attr("type") === "text") {
        elem.attr("type", "password");
    } else {
        setTimeout(function () {
            if (elem.val().length === 0) {
                elem.attr("type", "text");
                elem.hide();
                setTimeout(function () {
                    elem.show().focus();
                }, 1);
            }
        }, 1);
    }

    if (elem.val() === "" && e.type === "mousedown") {
        elem.hide();
        setTimeout(function () {
            elem.show().focus();
        }, 1);
    }

});

Моя версия 95.0.4638.69

Я столкнулся с подобной проблемой, и я решил ее, изменив имя моей формы с "login-form" на другое имя, которое ничего не значит, и решил его. Причина, по которой я не удалил атрибут имени, заключается в том, что, если я удалю атрибут имени, Chrome будет искать атрибут id и делать то же самое.

Вариант с использованием события onanimationstart (ReactJs) — 22 марта.

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

Я приведу пример кода в ReactJs, он может быть достаточно поясняющим, чтобы его можно было перенести в другой контекст.

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

      <input
 className={componentClass}
 placeholder={placeholder}
 onChange={handleChange}
 onFocus={onFocus}
 onMouseEnter={onHover}
 onMouseLeave={onHover}
 onBlur={onBlur}
 disabled={disabled}
 name={name}
 value={value}
 onAnimationStart={e => this.onAnimationStart(e)}
/>

Тогда приступим к onAnimationStartтело функции.

      onAnimationStart(event) {   
   // on autofill animation
   if (event.animationName === 'onAutoFillStart') {
     event.target?.labels[0].classList.add('grm-form__isAutofilled');
   }
 }

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

Ты упомянул:

Если щелкнуть где-нибудь на странице, то неважно, где будет заполнено значение input type="password".

Вот почему я просто использую $('body').click(); для имитации этого первого щелчка, после которого значение становится доступным в JavaScript.

Также я установил autocomplete="new-password" в поле пароля моей формы регистрации, чтобы поле не заполнялось автоматически, и пользователи должны были ввести новый пароль.

См. Эту страницу разработчиков Google для получения дополнительной информации.

Просто установите для атрибута автозаполнения имя пользователя для поля имени пользователя и новый пароль для поля пароля;

<input type="text" id="username" autocomplete="username">
<input type="password" id="password" autocomplete="new-password" >

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

Другие вопросы по тегам