Chrome Autofill / Autocomplete pas de valeur pour le mot de passe

Lorsque vous avez enregistré un nom d'utilisateur et un mot de passe pour un site, Chrome remplira automatiquement ce nom d'utilisateur et ce mot de passe, mais si vous essayez d'obtenir la valeur du champ de saisie du mot de passe, il est vide, même s'il existe une valeur là-bas ******.

Si vous cliquez sur quelque part sur la page, ignore où la valeur du input type="password" sera remplie.

C'est Fiddle user / pass de la structure du html et de la commande console.log . Il ne peut pas être vu ici, mais il peut être reproduit sur chaque page qui a un formulaire de connexion et le nom d'utilisateur et le mot de passe sont automatiquement remplis sur la charge de la page. Si vous inspectez la valeur du champ avant de cliquer sur n'importe où sur le site, il sera vide.

Ce n'est pas le cas dans Firefox ou Internet Explorer qu'il remplira la valeur de l'élément de input avec le mot de passe.

J'utilise Windows 7 Ultimate 64-bit OS et la version Google Chrome est 48.0.2564.97 m

Est-ce ce comportement normal, un bogue ou?

METTRE À JOUR:

Si vous cliquez sur F5 pour recharger la page et inspectez le champ du mot de passe, la valeur du mot de passe sera là. Si vous cliquez sur le bouton de rechargement dans Chrome dans le coin supérieur gauche, la valeur du champ du mot de passe sera une chaîne vide.

Cela semble être un bug dans Chrome. Lorsque Chrome remplit automatiquement un mot de passe sur une charge de page initiale (mais pas une actualisation), la valeur apparaît dans le champ de formulaire à l'écran, mais la requête de passwordField.value dans Javascript renvoie une chaîne vide. Si vous dépendez de cette valeur en Javascript, cela vous empêche de le faire. Une fois que l'utilisateur effectue une autre action sur la page, par exemple, en cliquant n'importe où sur la page, la valeur devient soudainement visible pour le Javascript.

Je ne suis pas vraiment sûr de savoir s'il s'agit d'un bug, ou s'il y a une raison de sécurité pour ce faire, par exemple, empêcher un cadre caché de voler votre mot de passe en essayant le navigateur de le remplir.

Une solution de contournement que nous avons utilisée est de détecter le changement de couleur d'arrière-plan que Chrome crée sur les champs qu'il a remplis automatiquement. Chrome couvre l'arrière-plan des champs auto-remplis en jaune, et cette modification est toujours visible pour Javascript même lorsque la valeur n'est pas. Détecter cela en Javascript nous permet de savoir que le champ a été rempli automatiquement avec une valeur, même si nous voyons la valeur vide dans Javascript. Dans notre cas, nous avons un formulaire de connexion où le bouton de soumission n'est pas activé jusqu'à ce que vous remplissiez quelque chose dans le champ du mot de passe, et la détection d'une valeur ou de la couleur d'arrière-plan de remplissage automatique soit suffisante pour déterminer si quelque chose se trouve dans le champ . Nous pouvons alors activer le bouton de soumission, et en cliquant sur le bouton (ou en appuyant sur enter) rend instantanément la valeur du champ du mot de passe visible pour Javascript car l'interaction avec la page corrige le problème, afin que nous puissions procéder normalement à partir de là.

Réponse de travail au 8 juillet 2016

Adam a déclaré correctement que c'est un bogue (ou comportement prévu). Cependant, aucune des réponses précédentes ne dit réellement comment résoudre ce problème, alors voici une méthode pour forcer Chrome à traiter la valeur automatique comme valeur réelle.

Plusieurs choses doivent se produire dans l'ordre, et cela ne doit fonctionner que dans Chrome et pas Firefox, d'où le if .

D'abord, nous nous concentrons sur l'élément. Nous créons ensuite un nouveau TextEvent et initTextEvent , qui ajoute dans une chaîne personnalisée que nous spécifions (j'ai utilisé "@@@@@") au début de la valeur. Cela déclenche que Google Chrome commence à agir comme si la valeur était réelle. Nous pouvons ensuite supprimer la chaîne personnalisée que nous avons ajoutée, puis nous nous sommes déconnectés.


Code:

 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(); 

Modifier le 10 août 2016

Cela fonctionne uniquement en Chrome sur Windows et Android. Ne fonctionne pas sur OSX. En outre, il cessera de fonctionner en septembre 2016, selon:

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

De plus, j'ai ouvert un ticket Chromium.

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

Au 12 août, un membre de l'équipe Chrome a déclaré sur le ticket ci-dessus que le comportement ne changera pas parce qu'il ne considère pas qu'il s'agisse d'un bug.

Suggestion de travail à long terme:

Cela dit, le comportement actuel a été modifié après la première mise en œuvre. L'utilisateur ne doit plus interagir avec l'entrée du mot de passe pour la valeur à déclarer. L'utilisateur doit maintenant interagir (envoyer un événement de souris ou de clavier) avec n'importe quelle partie de la page. Cela signifie que, tout en exécutant la validation sur pageload, ne fonctionnera toujours pas, en cliquant sur un bouton de soumission, le Chrome fera correctement état de la valeur du mot de passe. Le travail consiste alors à revalider toutes les entrées qui pourraient être remplies automatiquement, si c'est ce que vous essayez de faire, à soumettre.


Édition 13 décembre 2016:

Un nouveau ticket Chromium a été ouvert et il est mieux reçu. Si vous êtes intéressé par changer ce comportement de Chrome, connectez-vous ce nouveau ticket:

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

J'ai trouvé une solution à cette question qui fonctionne au moins pour mes besoins.

J'ai un formulaire de connexion que je souhaite cliquer sur Entrer dès qu'il se charge mais je rencontrais le problème de mot de passe vide dans Chrome.

Le suivant semble fonctionner, ce qui permet à la clé de saisie initiale d'échouer et à réessayer une fois que Chrome se réveille et fournit la valeur du mot de passe.

 $(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 } 

Une autre option à partir du 16 déc. / Chrome 54

Je ne peux pas obtenir la valeur du champ du mot de passe, mais, après "un court moment", je peux obtenir la longueur du mot de passe en le sélectionnant, ce qui est suffisant pour que je permette le bouton de soumission.

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

La solution de contournement spécifiée par Adam:

… détecte le changement de couleur d'arrière-plan que Chrome crée sur les champs qu'il a remplis automatiquement. Chrome couvre l'arrière-plan des champs auto-remplis en jaune, et cette modification est toujours visible pour Javascript même lorsque la valeur n'est pas. Détecter ceci en Javascript nous permet de savoir que le champ a été rempli automatiquement avec une valeur, même si nous voyons la valeur vide dans Javascript

J'avais comme ça: –

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

Où rgb (250, 255, 189) est la couleur jaune que Chrome applique aux entrées remplies automatiquement.

Avec Angular, le nouveau comportement de Chrome (permettant uniquement la lecture automatique des valeurs après l'interaction de l'utilisateur avec la page) se manifeste comme un problème lorsque vous utilisez la fonctionnalité de validation d'Angular dans certains scénarios (par exemple, en utilisant des méthodes standard / des attributs d'action Sur le formulaire). Lorsque le gestionnaire de soumission est exécuté immédiatement, il ne permet pas aux validateurs de formulaire de capturer les valeurs de remplissage automatique de Chrome.

Une solution que j'ai trouvée pour appeler explicitement la fonction $commitViewValue contrôleurs $commitViewValue dans le gestionnaire de soumission pour déclencher une révalidation avant le form.$valid vérification form.$valid ou form.invalid etc.

Exemple:

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

Bien que cela fonctionne pour nous jusqu'à maintenant, je serais très intéressé si quelqu'un a trouvé un autre travail plus élégant pour le problème.

Suite à ce que Andy Mercer a dit , voici mon travail. Comme beaucoup de gens, je n'ai pas besoin de la valeur de mot de passe réelle. J'ai vraiment besoin de savoir que la boîte de mot de passe a été remplie automatiquement, afin que je puisse afficher les messages de validation appropriés.

Personnellement, je n'utiliserais pas la solution proposée (pour détecter la cause du changement de couleur d'arrière-plan par le remplissage automatique de Chrome). Cette approche semble fragile. Cela dépend de cette couleur jaune qui ne change jamais. Mais il peut être modifié par des extensions et il existe d'autres navigateurs basés sur Blink (c'est-à-dire Opera) qui peuvent utiliser une couleur différente. Et il n'y a aucune promesse que Google n'utilisera pas de couleur différente à l'avenir. Cette méthode fonctionne indépendamment du style.

Tout d'abord, dans CSS, je définis le contenu de l' INPUT lorsque la pseudo-classe -webkit-autofil est appliquée:

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

Ensuite, j'ai créé une routine pour vérifier si le contenu doit être défini:

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

Enfin, j'ai interrogé la input pour permettre le temps de remplissage automatique:

 const input = document.querySelector("input[type=password]"); if (!checkAutofill(input)) { let interval = 0; const intervalId = setInterval(() => { if (checkAutofill(input) || interval++ >= 20) clearInterval(intervalId); }, 100); } 

Voici ma solution à ce problème:

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

Fondamentalement, le clic rend l'entrée visible pour l'utilisateur, alors je demande à l'utilisateur de cliquer et quand ils le font, je cache le message.

Pas la solution la plus élégante, mais probablement la plus rapide.

Le comportement prévu de Chrome est qu'un mot de passe rempli automatiquement a une value vide dans le DOM jusqu'à ce que l'utilisateur interagisse avec le cadre d'une manière ou l'autre, alors que chrome remplit effectivement la valeur. Jusqu'à ce moment, n'importe quelle validation côté client ou tentative d'ajax soumettre le formulaire verra le mot de passe vide.

Ce comportement «remplir le mot de passe sur l'interaction de l'image» est incohérent. J'ai trouvé que lorsque le formulaire est hébergé dans un iframe de même origine, il ne fonctionne que sur la première charge, et jamais sur les charges ultérieures.

Ceci est plus évident sur les formes ajax où le mot de passe autocomplete remplit sur la première charge, mais si ce mot de passe est invalide et que la requête ajax rend la forme DOM, le mot de passe automatiquement repris visuellement, mais la value n'est jamais remplie, indépendamment de l'interaction .

Aucune des solutions de rechange mentionnées, comme le déclenchement input événements de blur ou d' input n'a fonctionné dans ce scénario. La seule solution de contournement que j'ai trouvée consiste à réinitialiser la valeur du champ du mot de passe après que le processus ajax redéfinit le formulaire, par exemple:

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

Après ce qui précède, Chrome remplit réellement le mot de passe mais avec la value effectivement peuplée.

Dans mon cas d'utilisation actuel, j'utilise le Ajax.BeginForm d'ASP.NET et j'utilise la solution de contournement ci-dessus dans le rappel AjaxOptions.OnSuccess.

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

Cette solution a fonctionné dans mon cas. Utilisation de jQuery 3.1.1.

Il vient d'écrire une directive angulaire liée à cela. Fini avec le code suivant:

 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: il ne détecte pas 100% des temps, chrome peut prendre plus de 5 secondes pour remplir l'entrée.