How can I get browser to prompt to save password?

2019-01-01 00:02发布

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 in DIV on page
  3. User enters user/pass in fields and clicks submit. It's NOT a <form> -- user/pass are submitted via AJAX
  4. If user/pass are okay, page reloads with user logged in.
  5. If user/pass are bad, page does NOT reload but error message appears in DIV and user gets to try again.

Here's the problem: the browser never offers the usual "Save this password? Yes / Never / Not Now" prompt that it does for other sites.

I tried wrapping the <div> in <form> tags with "autocomplete='on'" but that made no difference.

Is it possible to get the browser to offer to store the password without a major rework of my login flow?

thanks Eric

p.s. to add to my question, I'm definitely working with browers that store passwords, and I've never clicked "never for this site" ...this is a technical issue with the browser not detecting that it's a login form, not operator error :-)

18条回答
梦该遗忘
2楼-- · 2019-01-01 00:39

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.

查看更多
冷夜・残月
3楼-- · 2019-01-01 00:40

I had similar problem, login was done with ajax, but browsers (firefox, chrome, safari and IE 7-10) would not offer to save password if form (#loginForm) is submitted with ajax.

As a SOLUTION I have added hidden submit input (#loginFormHiddenSubmit) to form that was submitted by ajax and after ajax call would return success I would trigger a click to hidden submit input. The page any way needed to refreshed. The click can be triggered with:

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

Reason why I have added hidden submit button is because:

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

would not offer to save password in IE (although it has worked in other browsers).

查看更多
倾城一夜雪
4楼-- · 2019-01-01 00:42

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.
查看更多
裙下三千臣
5楼-- · 2019-01-01 00:42

Your site is probably already in the list where the browser is told not to prompt for saving a password. In firefox, Options -> Security -> Remember password for sites[check box] - exceptions[button]

查看更多
无与为乐者.
6楼-- · 2019-01-01 00:47

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.

查看更多
弹指情弦暗扣
7楼-- · 2019-01-01 00:49

I found a complete solution for this question. (I've tested this in Chrome 27 and Firefox 21).

There are two things to know:

  1. Trigger 'Save password', and
  2. Restore the saved username/password

1. Trigger 'Save password':

For Firefox 21, 'Save password' is triggered when it detects that there is a form containing input text field and input password field is submitted. So we just need to use

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

someFunctionForLogin() does the ajax login and reload/redirect to the signed in page while event.preventDefault() blocks the original redirection due to submitting the form.

If you deal with Firefox only, the above solution is enough but it doesn't work in Chrome 27. Then you will ask how to trigger 'Save password' in Chrome 27.

For Chrome 27, 'Save password' is triggered after it is redirected to the page by submitting the form which contains input text field with attribute name='username' and input password field with attribute name='password'. Therefore, we cannot block the redirection due to submitting the form but we can make the redirection after we've done the ajax login. (If you want the ajax login not to reload the page or not to redirect to a page, unfortunately, my solution doesn't work.) Then, we can use

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

Button with type='button' will make the form not to be submitted when the button is clicked. Then, binding a function to the button for ajax login. Finally, calling $('#loginForm').submit(); redirects to the signed-in page. If the signed-in page is current page, then you can replace 'signedIn.xxx' by current page to make the 'refresh'.

Now, you will find that the method for Chrome 27 also works in Firefox 21. So it is better to use it.

2. Restore the saved username/password:

If you already have the loginForm hard-coded as HTML, then you will found no problem to restore the saved password in the loginForm.
However, the saved username/password will not be bind to the loginForm if you use js/jquery to make the loginForm dynamically, because the saved username/password is bind only when the document loads.
Therefore, you needed to hard-code the loginForm as HTML and use js/jquery to move/show/hide the loginForm dynamically.


Remark: If you do the ajax login, do not add autocomplete='off' in tag form like

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

autocomplete='off' will make the restoring username/password into the loginForm fails because you do not allow it 'autocompletes' the username/password.

查看更多
登录 后发表回答