Подтвердить что ты не робот

Chrome Autofill/Autocomplete не имеет значения для пароля

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

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

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

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

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

Это обычное поведение, ошибка или?

UPDATE:

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

Рабочий ответ от 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 сказал в вышеуказанном билете, что поведение не изменится, потому что они не считают его ошибкой.

Долгосрочное предложение:

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


Редактировать 13 декабря 2016 года:

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

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

Ответ 3

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

Лично я не использовал бы предлагаемое решение для обнаружения причины изменения цвета фона с помощью автозаполнения 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);
}

Ответ 4

Здесь мое решение этой проблемы:

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

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

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

Не самое элегантное решение, но, вероятно, самое быстрое.

Ответ 5

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

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

Мне понравилось: -

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

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

Ответ 6

Другой вариант по состоянию на 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);

Ответ 7

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

У меня есть форма входа в систему, в который я просто хочу нажать 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
}

Ответ 8

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

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% времени, хром может занять дольше 5 секунд, чтобы заполнить вход.

Ответ 9

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

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

Ответ 10

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

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

Пример:

function submit ($event) {
    // Allow model to be updated by Chrome autofill
    // @see http://stackoverflow.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
    }
}

Хотя это работает для нас до сих пор, мне было бы очень интересно, если кто-то нашел другую, более элегантную работу вокруг проблемы.

Ответ 11

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

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

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

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

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

После этого Chrome фактически автоматически запустит пароль, но с фактическим заполнением value.

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

Ответ 12

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

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

Ответ 13

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

Ответ 14

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

Ответ 15

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

[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);
    }

});

Ответ 16

Просто добавьте атрибут "имя" для ввода

Ответ 17

Очень ценю три лучших ответа здесь. Особенно Адам Энди и Бен. Если я могу добавить, в моем конкретном случае я хотел фактические значения входных данных, чтобы я мог запустить проверки на стороне клиента перед включением кнопки отправки. Недостаточно было знать, что значения присутствовали, но я хотел получить фактическое значение.

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

var evt = new MouseEvent("click", {
  view: window,
  clientX: 0
});

window.dispatchEvent(evt);
let iterations = 0;

const interval = setInterval(() => {
  const value = document.getElementById("email").value;
  if (!!value || iterations > 20) {
    console.log(value);
    return clearInterval(interval);
  }

  iterations++;
  console.log("not found -> repeat");
}, 100);

Хотя он использует интервал, Chrome заставляет нас придумывать хакерское решение, потому что другого выбора нет (как Энди так подробно рассказал нам)

Ответ 18

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

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

Ответ 19

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

Я думаю, что стоит упомянуть, что если вы хотите использовать его для стилевого оформления 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
}

Ответ 20

Вы упомянули:

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

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

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

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