How can I get browser to prompt to save password?

前端 未结 20 1253
面向向阳花
面向向阳花 2020-11-22 16:20

Hey, I\'m working on a web app that has a login dialog that works like this:

  1. User clicks \"login\"
  2. Login form HTML is loaded with AJAX and displayed i
相关标签:
20条回答
  • 2020-11-22 16:45

    I spent a lot of time reading the various answers on this thread, and for me, it was actually something slightly different (related, but different). On Mobile Safari (iOS devices), if the login form is HIDDEN when the page loads, the prompt will not appear (after you show the form then submit it). You can test with the following code, which displays the form 5 seconds after the page load. Remove the JS and the display: none and it works. I am yet to find a solution to this, just posted in case anyone else has the same issue and can not figure out the 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>
    
    0 讨论(0)
  • 2020-11-22 16:45

    I found a fairly elegant solution (or hack, whatever fits) for Prototype.JS users, being one of the last holdouts using Prototype. A simple substitution of corresponding jQuery methods should do the trick.

    First, make sure there's a <form> tag, and a submit button with a class name that can be referenced later (in this case faux-submit) that is nested inside an element with a style set to display:none, as illustrated below:

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

    Then create a click observer for the button, that will "submit" the form as illustrated:

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

    Then create a listener for submit event, and stop it. event.stop() will stop all submit events in the DOM unless it's wrapped in Event.findElement with the class of the hidden input button (as above, faux-submit):

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

    This is tested as working in Firefox 43 and Chrome 50.

    0 讨论(0)
  • 2020-11-22 16:46

    The following code is tested on

    • Chrome 39.0.2171.99m: WORKING
    • Android Chrome 39.0.2171.93: WORKING
    • Android stock-browser (Android 4.4): NOT WORKING
    • Internet Explorer 5+ (emulated): WORKING
    • Internet Explorer 11.0.9600.17498 / Update-Version: 11.0.15: WORKING
    • Firefox 35.0: WORKING

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

    Post-code:

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

    Remarks

    • For dynamic login-forms a call to window.external.AutoCompleteSaveForm is needed
    • Internet Explorer need a "password"-field to show the store-password-dialog
    • Internet Explorer seems to require a click on submit-button (even if it's a fake click)

    Here is a sample ajax login-code:

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

    Remarks

    • "account/login" sets a cookie if successful
    • Page-redirect ("manually" initiated by js-code) seems to be required. I also tested an iframe-post, but I was not successful with that.
    0 讨论(0)
  • 2020-11-22 16:49

    Using a button to login:

    If you use a type="button" with an onclick handler to login using ajax, then the browser won't offer to save the password.

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

    Since this form does not have a submit button and has no action field, the browser will not offer to save the password.


    Using a submit button to login:

    However, if you change the button to type="submit" and handle the submit, then the browser will offer to save the password.

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

    Using this method, the browser should offer to save the password.


    Here's the Javascript used in both methods:

    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
    }
    
    0 讨论(0)
  • 2020-11-22 16:51

    I tried spetson's answer but that didn't work for me on Chrome 18. What did work was to add a load handler to the iframe and not interrupting the submit (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();
    

    The 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() does an AJAX call and shows the loginForm div if it fails. (The web service will return 403 if the user isn't authenticated).

    Tested to work in FF and IE8 as well.

    0 讨论(0)
  • 2020-11-22 16:51

    The browser might not be able to detect that your form is a login form. According to some of the discussion in this previous question, a browser looks for form fields that look like <input type="password">. Is your password form field implemented similar to that?

    Edit: To answer your questions below, I think Firefox detects passwords by form.elements[n].type == "password" (iterating through all form elements) and then detects the username field by searching backwards through form elements for the text field immediately before the password field (more info here). From what I can tell, your login form needs to be part of a <form> or Firefox won't detect it.

    0 讨论(0)
提交回复
热议问题