web-dev-qa-db-fra.com

Désactivation du remplissage automatique de Safari sur les noms d'utilisateur et les mots de passe

Vous savez peut-être déjà que Safari possède un vilain bogue de remplissage automatique qui remplit les champs de courrier électronique, nom d'utilisateur et mot de passe, que vous ayez défini autocomplete="off" ou non.

Voici un formulaire de base:

<form action="/" method="post">
    <p>
        <label>E-mail</label>
        <input type="text" name="email" value="" />
    </p>
    <p>
        <label>Password</label>
        <input type="password" name="password" value="" />
    </p>
</form>

... Safari remplit automatiquement ces champs au chargement de la page comme il se doit, travail bien fait!

Si vous ajoutez autocomplete="off" aux champs et/ou à l'élément de formulaire, Safari remplit toujours automatiquement ces champs:

<form action="/" method="post" autocomplete="off">
    <p>
        <label>E-mail</label>
        <input type="text" name="email" value="" autocomplete="off" />
    </p>
    <p>
        <label>Password</label>
        <input type="password" name="password" value="" autocomplete="off" />
    </p>
</form>

Même cela ne fonctionne pas:

<form action="/" method="post" autocomplete="off">
    <p>
        <label>E-mail</label>
        <input type="text" name="secretfield1" value="" autocomplete="off"/>
    </p>
    <p>
        <label>Password</label>
        <input type="password" name="secretfield2" value="" autocomplete="off" />
    </p>
</form>

... puisque Safari recherche ces éléments <label> s’ils contiennent les mots "E-mail", "Mot de passe", etc. et poursuivent le remplissage automatique.

Aaaahhhhha !, j'ai pensé et j'ai essayé ceci:

<form action="/" method="post" autocomplete="off">
    <p>
        <label>%REPLACE_EMAIL_TITLE%</label>
        <input type="text" name="%REPLACE_EMAIL_NAME%" value="" autocomplete="off"/>
    </p>
    <p>
        <label>%REPLACE_PASSWORD_TITLE%</label>
        <input type="password" name="%REPLACE_PASSWORD_NAME%" value="" autocomplete="off" />
    </p>
</form>

... et remplacez% TAGS% par les vrais noms en utilisant JavaScript. Safari remplit automatiquement. Peu importe si vous définissez un délai de 10 secondes pour le remplacement.

Alors, est-ce vraiment la seule option?

<form action="/" method="post" autocomplete="off">
    <p>
        <label>That electronic postal address we all use, but can't write the title here because Safari fills this with YOUR information if you have autofill turned on</label>
        <input type="text" name="someelectronicpostaladdress" value="" autocomplete="off"/>
    </p>
    <p>
        <label>A set of characters, letters, numbers and special characters that is so secret that only you or the user you are changing it for knows, but can't write the title here because Safari sucks</label>
        <input type="password" name="setofseeecretcharacters" value="" autocomplete="off" />
    </p>
</form>

J'espère que non?

UPDATE: @skithund a signalé sur Twitter , que Safari reçoit une mise à jour 4.0.3 , qui mentionne "Login AutoFill". Est-ce que quelqu'un sait si cette mise à jour va résoudre ce problème?

44
Jari

J'ai eu le même problème. Et bien que ma solution ne soit pas parfaite, elle semble fonctionner. Fondamentalement, Safari semble rechercher un champ de saisie avec mot de passe et nom d'utilisateur et tente toujours de le remplir. Ma solution a donc été d’ajouter un faux nom d’utilisateur et mot de passe avant celui que Safari pourrait remplir. J'ai essayé d'utiliser style="display: none;" mais cela n'a pas fonctionné. Donc, finalement, j'ai juste utilisé style="position:absolute; top:-50px;" et cela a caché le champ de saisie et a semblé bien fonctionner. Je ne voulais pas utiliser JavaScript, mais je suppose que vous pouvez le cacher avec JavaScript.

Maintenant, Safari n'a jamais complété automatiquement mes champs de nom d'utilisateur et de mot de passe.

34
Richard perris

Correction: le navigateur remplissait automatiquement en mode lecture seule et définissait le focus en écriture

 <input type="password" readonly onfocus="this.removeAttribute('readonly');"/>

(focus = clic de souris et tabulation dans les champs)

Mise à jour: Mobile Safari définit le curseur dans le champ, mais n'affiche pas le clavier virtuel. Le nouveau correctif fonctionne comme avant mais gère le clavier virtuel:

<input id="email" readonly type="email" onfocus="if (this.hasAttribute('readonly')) {
    this.removeAttribute('readonly');
    // fix for mobile safari to show virtual keyboard
    this.blur();    this.focus();  }" />

Démo en direct https://jsfiddle.net/danielsuess/n0scguv6/

// UpdateEnd

Explication: le navigateur remplit automatiquement les informations d'identification avec un champ de texte incorrect?

Ok, vous venez de remarquer que:

Safari remplit automatiquement. Peu importe [le nom des champs] @Jari

et il y a une hypothèse que:

Safari semble rechercher un champ de saisie avec mot de passe et nom d'utilisateur et essaie toujours de le remplir @ user3172174

Parfois, je remarque ce comportement étrange sur Chrome et Safari, quand il y a des champs de mot de passe dans le même formulaire. Je suppose que le navigateur cherche un champ de mot de passe pour insérer vos informations d'identification enregistrées. Puis il (remplit automatiquement nom_utilisateur dans le champ de saisie textlike le plus proche, qui apparaît avant le champ mot de passe) dans DOM (devinement dû à l'observation). Comme le navigateur est la dernière instance et que vous ne pouvez pas le contrôler, 

parfois même l'auto-complétion = off n'empêche pas de renseigner les informations d'identification dans des champs incorrects, mais pas dans le champ utilisateur ou pseudonyme. 

Ce correctif ci-dessus en lecture seule a fonctionné pour moi.

15
dsuess

L'ajout du fichier css à l'entrée masquera le pseudo-élément du bouton safari et les utilisateurs ne pourront pas utiliser la fonction de saisie semi-automatique 

input::-webkit-contacts-auto-fill-button, 
input::-webkit-credentials-auto-fill-button {
  visibility: hidden;
  pointer-events: none;
  position: absolute;
  right: 0;
}

10
Vadizar

On a déjà répondu à cette question avec succès, mais à la date d'aujourd'hui, la solution ne fonctionnait pas pour moi sans apporter des modifications étrangement particulières - je la note donc autant ici pour ma propre référence si je décide d'y revenir. comme pour tout le monde.

  • La fausse entrée doit être après la véritable entrée de courrier électronique dans le dom.
  • La fausse entrée nécessite une fausse étiquette.
  • La fausse étiquette ne peut être absolument positionnée.
  • Impossible d'utiliser l'affichage, la visibilité ou l'opacité pour masquer les faux éléments.

La seule solution que j'ai trouvée était de couper la visibilité des faux éléments avec overflow: hidden.

<label for="user_email">Email</label>
<input autocomplete="off" type="text" value="[email protected]" name="user[email]" id="user_email">
<!-- Safari looks for email inputs and overwrites the existing value with the user's personal email. This hack catches the autofill in a hidden input. -->
<label for="fake_email" aria-hidden="true" style="height: 1px; width: 1px; overflow: hidden; clip: rect(1px, 1px, 1px, 1px)">Email</label>
<input type="text" name="fake[email]" id="fake_email" style="height: 1px; width: 1px; overflow: hidden; clip: rect(1px, 1px, 1px, 1px)" tab-index="-1" aria-hidden="true">

Pour mémoire, le cas particulier pour lequel ce piratage a été utile est celui où un administrateur modifie le profil d’autres utilisateurs et où Safari remplace le courrier électronique de l’utilisateur par le courrier électronique de l’administrateur. Nous avons décidé que, pour le petit nombre (mais frustrant) de demandes d'assistance générées par cette "fonctionnalité" de Safari, il ne vaut pas la peine de conserver un bidouillage qui semble devoir évoluer à mesure que Safari le renforce, mais plutôt fournir un support à ces utilisateurs. sur la façon de désactiver le remplissage automatique.

5
dontwakemeup

Je ne peux pas croire que c'est encore un problème si longtemps après que ça a été rapporté. Les solutions ci-dessus ne fonctionnaient pas pour moi, car safari semblait savoir quand l'élément n'était pas affiché ou hors écran, mais ce qui suit fonctionnait pour moi:

<div style="position:absolute;height:0px; overflow:hidden; ">
  Username <input type="text" name="fake_safari_username" >
  Password <input type="password" name="fake_safari_password">
</div>

J'espère que c'est utile pour quelqu'un!

2
Ben

Le comportement étrange de la saisie semi-automatique par défaut de Safari m'a également mordu, mais plutôt que de le désactiver complètement, j'ai réussi à le faire fonctionner pour moi en suivant les instructions à https://www.chromium.org/developers/design-documents/ forme-styles-que-chrome-comprend

Plus précisément, je mets autocomplete="username" dans le champ Nom d'utilisateur et autocomplete="password-current" dans le champ Mot de passe. Cela indique au navigateur quels champs à remplir automatiquement, plutôt que de le deviner, et il corrige la saisie semi-automatique pour mon cas d'utilisation.

Cette approche fonctionne à la fois pour les formulaires de connexion "email en premier" (le champ mot de passe n'est pas immédiatement visible, par exemple, le login Google), ainsi que pour les formulaires de connexion classiques avec les champs nom d'utilisateur et mot de passe visibles.

1

Mon problème: J'ai une section dans une zone d'administration qui permet aux utilisateurs de définir toutes les valeurs de langue, dont certaines contiennent les mots "mot de passe", "email", "adresse email" etc. Je ne les souhaite pas les valeurs à renseigner avec les détails de l'utilisateur, elles servent à créer des traductions dans une autre langue. Il s’agit alors d’une exception valide à la "préférence du navigateur" conjuguée ".

Ma solution: J'ai simplement créé des noms alternatifs:

$name = str_replace('email','em___l',$name);
$name = str_replace('password','pa___d',$name);
<input type="text" name="<?=$name?>" id="<?=$name?>" />

Ensuite, lorsque le formulaire est posté:

foreach($_POST as $name=>$value) {
    $name=str_replace('em___l','email',$name);
    $name=str_replace('pa___d','password',$name);
    $_POST[$name]=$value;
}

C'est la seule méthode qui a fonctionné pour moi.

0
vendo

Mieux que d'utiliser JS pour effacer le contenu - il suffit de créer un faux mot de passe:

<input type="text" name="user" />
<input fake_pass type="password" style="display:none"/>
<input type="password" name="pass" />

Un type password doublé met le navigateur dans l'incertitude afin qu'il ne complète que le nom d'utilisateur. 

fake_passinput ne devrait pas avoir l'attribut name pour garder $_POST clean!

0
bortunac

J'ai eu le même problème soudainement dans un spa avec React in Mobile Safari 10.3.1

Je n'ai besoin d'aucune solution de contournement complexe auparavant dans tous les navigateurs testés, même Mobile Safari IOS 10.2

Mais depuis 10.3.1, le nom d'utilisateur ou le mot de passe sera rempli dans les champs mentionnant les mots 'mot de passe', 'email', 'nom d'utilisateur' dans tous les formulaires après la connexion avec l'option de rappel actif. Il semble que l'arborescence DOM rendue soit "analysée" à l'aide d'une recherche en texte intégral, puis que l'agent utilisateur remplisse les données sans respecter aucun paramètre autocomplete = "off" . Il se produit également sur le texte de substitution d'un champ Donc, vous devez être très prudent avec les noms, lorsque vous ne voulez pas avoir un nom d'utilisateur ou un mot de passe prérempli dans des endroits où ces données ne sont pas utiles.

La seule solution après des heures d’enquête a été celle publiée ici aussi . Fournissez un champ de saisie nommé "email" et cachez le div contenant de hauteur: 0px, débordement: caché. 

0
user767644

Supprimer l'élément <form>. Pour conserver le comportement du formulaire, vous pouvez écouter l'événement keypress afin que les champs de saisie gèrent la touche enter. Juste au cas où j'aurais enlevé input type="submit" aussi. Vous pouvez utiliser button type="button".

0
Ikrom

Les solutions CSS display: none mentionnées ici ne fonctionnaient pas pour moi (octobre 2016). J'ai corrigé ce problème avec JavaScript.

Le navigateur ne se souvient pas des mots de passe, cela ne me dérange pas, mais je voulais éviter un mauvais remplissage automatique. Dans mon cas, un formulaire avec un champ mot de passe et aucun champ nom d'utilisateur associé. (Formulaire d'édition d'utilisateur sur le site Drupal 7, où le champ mot de passe n'est requis que pour certaines opérations.) Quoi que j'ai essayé, Safari trouverait un champ victime pour le nom d'utilisateur du mot de passe rempli automatiquement (le champ placé visuellement auparavant, par exemple).

Je rétablis la valeur d'origine dès que Safari effectue la saisie automatique. J'essaie cela uniquement pendant les 2 premières secondes après le chargement de la page. Une valeur probablement inférieure est OK. Mes tests ont montré que le remplissage automatique se produit environ 250 ms après le chargement de la page (bien que j'imagine que ce nombre dépend beaucoup de la manière dont la page est construite et chargée).

Voici mon code JavaScript (avec jQuery):

// Workaround for Safari autofill of the e-mail field with the username.
// Try every 50ms during 2s to reset the e-mail to its original value.
// Prevent this reset if user might have changed the e-mail himself, by
// detecting focus on the field.
if ($('#edit-mail').length) {
  var element = $('#edit-mail');
  var original = element.attr('value');
  var interval = setInterval(function() {
    if ($(document.activeElement).is(element)) {
      stop();
    } else if (element.val() != original) {
      element.val(original);
      stop();
    }
  }, 50);
  var stop = function() {
    clearTimeout(timeout);
    clearInterval(interval);
  }
  var timeout = setTimeout(function() {
    clearInterval(interval);
  }, 2000);
}
0
François

Vous pouvez essayer cette variante. Ça marche pour moi. Si vous modifiez la valeur du champ une fois, Safari la modifiera à nouveau. Si l'utilisateur clique sur ce champ, la valeur ne sera pas modifiée automatiquement par Safari.

  $.browser.chrome = /chrome/.test(navigator.userAgent.toLowerCase());
        if($.browser.chrome){
            $.browser.safari = false;
        }

        var isChanged=false;

        $('#Email').change(function () {
            if ($.browser.safari && !isChanged) {
                $('#Email').val('@Model.Email');
            }
        });

        $('#Email').click(function () {
            if ( $.browser.safari && !isChanged) {
                isChanged = true;
            }
        }); var isChangePassword = false;
    $('#OldPassword').change(function () {
        if ($.browser.safari && !isChangePassword) {
            $('#OldPassword').val('');
        }
    });

    $('#OldPassword').click(function () {
        if ($.browser.safari && !isChangePassword) {
            isChangePassword= true;
        }
    });
0
Iuliia Artiukh

Il semble que les programmeurs de navigateur pensent en savoir plus que les rédacteurs de sites Web. Bien qu'il soit parfois pratique de permettre à l'utilisateur de sauvegarder des mots de passe, il existe d'autres moments où il y a un risque de sécurité. Pour ces moments, cette solution de contournement pourrait aider: 

Commencez par utiliser une entrée de texte conventionnelle au lieu du type "mot de passe".

Password: &nbsp <input type="text" id="fkpass" name="bxpass" class="tinp" size="20" />

Ensuite, si vous le souhaitez, placez le focus sur le champ de saisie.

<BODY onLoad="fitform()">

Mettez le JS à la fin de la page. 

<script type="text/javascript">
document.entry.fkpass.focus();
function fitform() {
document.getElementById('fkpass').autocomplete = 'off';
}
</script>

Vous avez maintenant un champ de formulaire conventionnel. A quoi bon ça?
Modifiez le style CSS pour cette entrée afin qu’elle utilise une police composée uniquement de «puces» au lieu de caractères. 

<style type="text/css">
@font-face { font-family: fdot; src: url('images/dot5.ttf'); }
@font-face { font-family: idot; src: url('images/dot5.eot'); }
@font-face { font-family: wdot; src: url('images/dot5.woff'); }
@font-face { font-family: w2dot; src: url('images/dot5.woff2'); }
.tinp { font-family: fdot, idot, wdot, w2dot; color: #000; font-size:18px; }
</style>

Oui, vous pouvez "ranger" le code et y ajouter .svg. 

Quoi qu'il en soit, le résultat final ne peut pas être distingué de la saisie du mot de passe "réel" et le navigateur ne propose pas de l'enregistrer. 

Si vous voulez la police, c'est ici . Il a été créé avec CorelDraw et converti avec un utilitaire de conversion de contrôleur Web en ligne. (dot_webfont_kit.Zip 19.3k)

J'espère que ça aide. 

0
imillard