web-dev-qa-db-fra.com

Comment puis-je obtenir que le navigateur invite à enregistrer le mot de passe?

Bonjour, je travaille sur une application Web dotée d'une boîte de dialogue de connexion qui fonctionne comme suit:

  1. L'utilisateur clique sur "login"
  2. Le formulaire de connexion HTML est chargé avec AJAX et affiché dans DIV sur la page
  3. L'utilisateur entre l'utilisateur/passe dans les champs et clique sur soumettre. Ce n'est pas un <form> - l'utilisateur/le passe sont soumis via AJAX
  4. Si utilisateur/passe est correct, la page est rechargée avec l'utilisateur connecté.
  5. Si l'utilisateur/le mot de passe sont incorrects, la page ne se recharge PAS, mais un message d'erreur apparaît dans DIV et l'utilisateur peut réessayer.

Voici le problème: le navigateur n’offre jamais l’invitation habituelle "Enregistrer ce mot de passe? Oui/Jamais/Pas maintenant" comme il le fait pour d’autres sites.

J'ai essayé d'envelopper le <div> dans <form> balises avec "autocomplete = 'on'" mais cela ne faisait aucune différence.

Est-il possible de demander au navigateur de stocker le mot de passe sans retouche majeure de mon flux de connexion?

merci Eric

p.s. Pour ajouter à ma question, je travaille certainement avec des serveurs qui stockent des mots de passe, et je n'ai jamais cliqué sur "jamais pour ce site" ... Il s'agit d'un problème technique, le navigateur ne détectant pas qu'il s'agit d'un formulaire de connexion, et non d'un opérateur. Erreur :-)

129
Eric

J'ai trouvé une solution complète pour cette question. (J'ai testé cela dans Chrome 27 et Firefox 21).

Il y a deux choses à savoir:

  1. Déclenchez "Enregistrer le mot de passe", et
  2. Restaurer le nom d'utilisateur/mot de passe enregistré

1. Déclencheur 'Enregistrer le mot de passe':

Pour Firefox 21 , "Enregistrer le mot de passe" est déclenché lorsqu'il détecte qu'il existe un formulaire contenant un champ de saisie de texte et un mot de passe. le champ est soumis. Donc nous avons juste besoin d'utiliser

$('#loginButton').click(someFunctionForLogin);
$('#loginForm').submit(function(event){event.preventDefault();});

someFunctionForLogin() effectue la connexion ajax et recharge/redirige vers la page de connexion, tandis que event.preventDefault() bloque la redirection d'origine en raison de la soumission du formulaire.

Si vous n’utilisez que Firefox, la solution ci-dessus est suffisante mais ne fonctionne pas dans Chrome 27.). Ensuite, vous demanderez comment déclencher "Enregistrer le mot de passe" dans Chrome 27.

Pour Chrome 27 , "Enregistrer le mot de passe" est déclenché après il est redirigé vers la page par soumission du formulaire contenant le champ de saisie avec attribut name = 'nom d'utilisateur' et champ de saisie du mot de passe avec attribut name = 'mot de passe'. Par conséquent, nous ne pouvons pas bloquer la redirection en raison de la soumission du formulaire, mais nous pouvons effectuer la redirection une fois la connexion ajax établie. (Si vous voulez que le login ajax ne recharge pas la page ou ne redirige pas vers une page, malheureusement, ma solution ne fonctionne pas.) Nous pouvons alors utiliser

<form id='loginForm' action='signedIn.xxx' method='post'>
    <input type='text' name='username'>
    <input type='password' name='password'>
    <button id='loginButton' type='button'>Login</button>
</form>
<script>
    $('#loginButton').click(someFunctionForLogin);
    function someFunctionForLogin(){
        if(/*ajax login success*/) {
            $('#loginForm').submit();
        }
        else {
            //do something to show login fail(e.g. display fail messages)
        }
    }
</script>

Bouton avec type = 'bouton' fera que le formulaire ne sera pas soumis lorsque le bouton sera cliqué. Ensuite, liez une fonction au bouton pour la connexion ajax. Enfin, l'appel de $('#loginForm').submit(); redirige vers la page de connexion. Si la page de connexion est la page en cours, vous pouvez remplacer "signedIn.xxx" par la page en cours pour "actualiser".

Maintenant, vous constaterez que la méthode pour Chrome 27 fonctionne également dans Firefox 21). Il est donc préférable de l’utiliser.

2. Restaurer le nom d'utilisateur/mot de passe enregistré:

Si vous avez déjà codé en dur le code loginForm en HTML, vous ne trouverez aucun problème pour restaurer le mot de passe enregistré dans le formulaire loginForm.
Cependant, le nom d'utilisateur/mot de passe enregistré ne sera pas lié à loginForm si vous utilisez js/jquery pour créer le loginForm de manière dynamique, car le nom d'utilisateur/mot de passe enregistré est lié uniquement lors du chargement du document.
Par conséquent, vous deviez coder en dur le loginForm en HTML et utiliser js/jquery pour déplacer/afficher/masquer le loginForm de manière dynamique.


Remarque: Si vous vous connectez en ajax, n'ajoutez pas autocomplete='off' Sous la forme d'une balise comme

<form id='loginForm' action='signedIn.xxx' autocomplete='off'>

autocomplete='off' Fera que le nom d'utilisateur/mot de passe de restauration dans le formulaire de connexion échoue parce que vous ne le permettez pas de "compléter automatiquement" le nom d'utilisateur/mot de passe.

64
Timespace7

Utiliser un bouton pour vous connecter:

Si vous utilisez un type="button" avec un gestionnaire onclick pour se connecter avec ajax, puis le le navigateur ne propose pas pour enregistrer le mot de passe.

<form id="loginform">
 <input name="username" type="text" />
 <input name="password" type="password" />
 <input name="doLogin"  type="button" value="Login" onclick="login(this.form);" />
</form>

Puisque ce formulaire n'a pas de bouton d'envoi et n'a pas de champ d'action, le navigateur ne proposera pas de sauvegarder le mot de passe.


Utiliser un bouton submit pour vous connecter:

Cependant, si vous changez le bouton en type="submit" et gérer l'envoi, puis le le navigateur proposera pour enregistrer le mot de passe.

<form id="loginform" action="login.php" onSubmit="return login(this);">
 <input name="username" type="text" />
 <input name="password" type="password" />
 <input name="doLogin"  type="submit" value="Login" />
</form>

En utilisant cette méthode, le navigateur devrait proposer de sauvegarder le mot de passe.


Voici le Javascript utilisé dans les deux méthodes:

function login(f){
    var username = f.username.value;
    var password = f.password.value;

    /* Make your validation and ajax magic here. */

    return false; //or the form will post your data to login.php
}
40
spetson

J'y ai moi-même eu du mal à résoudre ce problème et j'ai enfin pu comprendre le problème et les causes de son échec.

Tout cela provenait du fait que mon formulaire de connexion était injecté de manière dynamique dans la page (en utilisant backbone.js). Dès que j'ai intégré mon formulaire de connexion directement dans mon fichier index.html, tout a fonctionné comme un charme.

Je pense que cela est dû au fait que le navigateur doit savoir qu’il existe un formulaire de connexion existant, mais comme le mien était injecté de manière dynamique dans la page, il ne savait pas qu’il existait un "vrai" formulaire de connexion.

15
TK421

Cette solution a fonctionné pour moi posté par Eric sur les forums de codage


La raison pour laquelle cela n’invite pas, c’est que le navigateur a besoin que la page soit physiquement pour se rafraîchir sur le serveur. Un petit truc que vous pouvez faire est d'effectuer deux actions avec le formulaire. La première action est soumise à l’appel de votre code Ajax. Aussi, le formulaire cible un iframe caché.

Code:

<iframe src="ablankpage.htm" id="temp" name="temp" style="display:none"></iframe>
<form target="temp" onsubmit="yourAjaxCall();">

Voir si cela provoque l'invite à apparaître.

Eric


Publié le http://www.codingforums.com/showthread.php?t=123007

12
Vincent

Il existe une solution ltime pour forcer tous les navigateurs (testé: chrome 25, safari 5.1, IE10, Firefox 16)) à demander de sauvegarder le mot de passe en utilisant jQuery et ajax demande:

JS:

$(document).ready(function() {
    $('form').bind('submit', $('form'), function(event) {
        var form = this;

        event.preventDefault();
        event.stopPropagation();

        if (form.submitted) {
            return;
        }

        form.submitted = true;

        $.ajax({
            url: '/login/api/jsonrpc/',
            data: {
                username: $('input[name=username]').val(),
                password: $('input[name=password]').val()
            },
            success: function(response) {
                form.submitted = false;
                form.submit(); //invoke the save password in browser
            }
        });
    });
});

HTML:

<form id="loginform" action="login.php" autocomplete="on">
    <label for="username">Username</label>
    <input name="username" type="text" value="" autocomplete="on" />
    <label for="password">Password</label>
    <input name="password" type="password" value="" autocomplete="on" />
   <input type="submit" name="doLogin" value="Login" />
</form>

L'astuce consiste à arrêter le formulaire pour qu'il l'envoie à sa propre manière (event.stopPropagation ()). Envoyez plutôt votre propre code ($ .ajax ()). Dans le rappel de succès de ajax, soumettez à nouveau le formulaire afin que le navigateur le saisisse et affiche le demande de sauvegarde du mot de passe. Vous pouvez également ajouter un gestionnaire d'erreur, etc.

J'espère que ça a aidé quelqu'un.

11
Michal Roharik

J'ai essayé réponse de spetson mais cela ne fonctionnait pas pour moi le Chrome 18. Ce qui a bien fonctionné a été d'ajouter un gestionnaire de chargement à l'iframe et de ne pas interrompre l'envoi ( jQuery 1.7):

function getSessions() {
    $.getJSON("sessions", function (data, textStatus) {
        // Do stuff
    }).error(function () { $('#loginForm').fadeIn(); });
}
$('form', '#loginForm').submit(function (e) {
    $('#loginForm').fadeOut();
}); 
$('#loginframe').on('load', getSessions);
getSessions();

Le HTML:

<div id="loginForm">
    <h3>Please log in</h3>
    <form action="/login" method="post" target="loginframe">
            <label>Username :</label>
            <input type="text" name="login" id="username" />
            <label>Password :</label>
            <input type="password" name="password" id="password"/>
            <br/>
            <button type="submit" id="loginB" name="loginB">Login!</button>
    </form>
</div>
<iframe id="loginframe" name="loginframe"></iframe>

getSessions () effectue un appel AJAX et affiche le div de loginForm en cas d'échec. (Le service Web renverra 403 si l'utilisateur n'est pas authentifié).

Testé pour fonctionner dans FF et IE8 également.

7
w00t

Le navigateur peut ne pas être en mesure de détecter que votre formulaire est un formulaire de connexion. Selon certaines des discussions dans cette question précédente , un navigateur recherche les champs de formulaire qui ressemblent à <input type="password">. Le champ de votre mot de passe implémenté est-il similaire à celui-ci?

Edit: Pour répondre à vos questions ci-dessous, je pense que Firefox détecte les mots de passe par form.elements[n].type == "password" (en parcourant tous les éléments du formulaire), puis détecte le champ nom d'utilisateur en recherchant en arrière le contenu dans les éléments du formulaire, juste avant le champ mot de passe (plus d'informations ici ). D'après ce que je peux dire, votre formulaire de connexion doit faire partie d'un <form> ou Firefox ne le détectera pas.

4
bta

J'ai passé beaucoup de temps à lire les différentes réponses sur ce fil, et pour moi, c'était en fait quelque chose de légèrement différent (lié, mais différent). Sur Mobile Safari (appareils iOS), si le formulaire de connexion est masqué lors du chargement de la page, l'invite n'apparaît pas (une fois que vous avez affiché le formulaire, vous l'avez envoyé). Vous pouvez tester avec le code suivant, qui affiche le formulaire 5 secondes après le chargement de la page. Supprimez le JS et l’affichage: aucun et cela fonctionne. Je n'ai pas encore trouvé de solution à ce problème, je viens de le signaler au cas où quelqu'un d'autre aurait le même problème et ne pourrait pas en déterminer la cause.

JS:

$(function() {
  setTimeout(function() {
    $('form').fadeIn();
  }, 5000);
});

HTML:

<form method="POST" style="display: none;">
  <input name='email' id='email' type='email' placeholder='email' />
  <input name='password' id='password' type='password' placeholder='password' />
  <button type="submit">LOGIN</button>
</form>
1
captainclam

J'ai trouvé une solution assez élégante (ou bidouillage, à votre convenance) pour les utilisateurs de Prototype.JS, l'un des derniers à utiliser Prototype. Une simple substitution des méthodes jQuery correspondantes devrait faire l'affaire.

Tout d’abord, assurez-vous qu’il existe une balise <form> Et un bouton d'envoi avec un nom de classe pouvant être référencé ultérieurement (dans ce cas faux-submit) Qui est imbriqué dans un élément avec un style défini sur display:none, Comme illustré ci-dessous:

<form id="login_form" action="somewhere.php" method="post">
    <input type="text" name="login" />
    <input type="password" name="password" />
    <div style="display:none">
        <input class="faux-submit" type="submit" value="Submit" />
    </div>
    <button id="submit_button">Login</button>
</form>

Créez ensuite un observateur de clic pour le button, qui "soumettra" le formulaire tel qu’illustré:

$('submit_button').observe('click', function(event) {
    $('login_form').submit();
});

Créez ensuite un écouteur pour l'événement submit et arrêtez-le. event.stop() arrêtera tous les événements de soumission dans le DOM à moins que celui-ci soit enveloppé dans Event.findElement avec la classe du bouton de saisie masqué (comme ci-dessus, faux-submit):

document.observe('submit', function(event) {
    if (event.findElement(".faux-submit")) { 
        event.stop();
    }
});

Ceci est testé pour fonctionner dans Firefox 43 et Chrome 50.

1
mwieczorek

Le code suivant est testé sur

  • Chrome 39.0.2171.99m: TRAVAIL
  • Android Chrome 39.0.2171.93: TRAVAIL
  • Stock-browser Android (Android 4.4): ne fonctionne pas
  • Internet Explorer 5+ (émulé): TRAVAIL
  • Internet Explorer 11.0.9600.17498/Update-Version: 11.0.15: TRAVAIL
  • Firefox 35.0: TRAVAIL

JS-Fiddle:
http://jsfiddle.net/ocozggqu/

Code postal:

// modified post-code from https://stackoverflow.com/questions/133925/javascript-post-request-like-a-form-submit
function post(path, params, method)
{
    method = method || "post"; // Set method to post by default if not specified.

    // The rest of this code assumes you are not using a library.
    // It can be made less wordy if you use one.

    var form = document.createElement("form");
    form.id = "dynamicform" + Math.random();
    form.setAttribute("method", method);
    form.setAttribute("action", path);
    form.setAttribute("style", "display: none");
    // Internet Explorer needs this
    form.setAttribute("onsubmit", "window.external.AutoCompleteSaveForm(document.getElementById('" + form.id + "'))");

    for (var key in params)
    {
        if (params.hasOwnProperty(key))
        {
            var hiddenField = document.createElement("input");
            // Internet Explorer needs a "password"-field to show the store-password-dialog
            hiddenField.setAttribute("type", key == "password" ? "password" : "text");
            hiddenField.setAttribute("name", key);
            hiddenField.setAttribute("value", params[key]);

            form.appendChild(hiddenField);
        }
    }

    var submitButton = document.createElement("input");
    submitButton.setAttribute("type", "submit");

    form.appendChild(submitButton);

    document.body.appendChild(form);

    //form.submit(); does not work on Internet Explorer
    submitButton.click(); // "click" on submit-button needed for Internet Explorer
}

Remarques

  • Pour les formulaires de connexion dynamiques, un appel à window.external.AutoCompleteSaveForm est nécessaire
  • Internet Explorer besoin d'un "champ mot de passe" pour afficher la boîte de dialogue store-password
  • Internet Explorer semble nécessite un clic sur le bouton d'envoi (même s'il s'agit d'un faux clic)

Voici un exemple de code de connexion ajax:

function login(username, password, remember, redirectUrl)
{
    // "account/login" sets a cookie if successful
    return $.postJSON("account/login", {
        username: username,
        password: password,
        remember: remember,
        returnUrl: redirectUrl
    })
    .done(function ()
    {
        // login succeeded, issue a manual page-redirect to show the store-password-dialog
        post(
            redirectUrl,
            {
                username: username,
                password: password,
                remember: remember,
                returnUrl: redirectUrl
            },
            "post");
    })
    .fail(function ()
    {
        // show error
    });
};

Remarques

  • "account/login" définit un cookie en cas de succès
  • Page-redirect ("lancé manuellement" par js-code) semble être nécessaire. J'ai également testé un post iframe, mais je n'ai pas réussi avec cela.
1
David Rettenbacher

J'ai eu un problème similaire, la connexion s'est faite avec ajax, mais les navigateurs (firefox, chrome, safari et IE 7-10) ne proposent pas de sauvegarder le mot de passe si le formulaire (#loginForm) est soumis avec ajax .

En tant que SOLUTION j'ai ajouté une entrée de soumission masquée (#loginFormHiddenSubmit) au formulaire qui a été soumis par ajax et après que l'appel ajax renvoie un succès, je déclencherais un clic sur masqué soumettre l'entrée. La page de toute façon nécessaire pour rafraîchir. Le clic peut être déclenché avec:

jQuery('#loginFormHiddenSubmit').click();

La raison pour laquelle j'ai ajouté un bouton de soumission caché est que:

jQuery('#loginForm').submit();

ne proposerait pas de sauvegarder le mot de passe dans IE (même si cela a fonctionné dans d'autres navigateurs).

0
Igor

Votre site est probablement déjà dans la liste et le navigateur ne doit pas Demander de sauvegarder un mot de passe. Dans Firefox, Options -> Sécurité -> Mémoriser le mot de passe pour les sites [case à cocher] - exceptions [bouton]

0
Dave.Sol

ajoutez un peu plus d'informations à la réponse de @Michal Roharik.

si votre appel ajax renverra une URL de retour, vous devez utiliser jquery pour modifier l'attribut d'action de formulaire en cette URL avant d'appeler form.submit.

ex.

$(form).attr('action', ReturnPath);
form.submitted = false;
form.submit(); 
0
maxisam