ajax 如何让浏览器提示保存密码?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2382329/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 10:51:51  来源:igfitidea点击:

How can I get browser to prompt to save password?

ajaxfirefoxbrowserlogin

提问by Eric

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.
  1. 用户点击“登录”
  2. 登录表单 HTML 加载 AJAX 并显示在页面上的 DIV 中
  3. 用户在字段中输入用户/通行证并点击提交。这不是<form>-- 用户/通行证是通过 AJAX 提交的
  4. 如果用户/通行证没问题,页面会在用户登录时重新加载。
  5. 如果用户/通行证错误,页面不会重新加载,但 DIV 中会出现错误消息,用户可以重试。

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.

我尝试用“autocomplete='on'”包装<div>in<form>标签,但这没有区别。

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

ps 添加到我的问题中,我肯定在使用存储密码的浏览器,而且我从来没有点击过“从不用于此站点”......这是浏览器没有检测到它是登录表单的技术问题,而不是操作员错误:-)

采纳答案by Timespace7

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

我找到了这个问题的完整解决方案。(我已经在 Chrome 27 和 Firefox 21 中对此进行了测试)。

There are two things to know:

有两件事要知道:

  1. Trigger 'Save password', and
  2. Restore the saved username/password
  1. 触发“保存密码”,然后
  2. 恢复保存的用户名/密码

1. Trigger 'Save password':

1. 触发“保存密码”:

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

对于Firefox 21,当它检测到存在包含输入文本字段的表单并提交输入密码字段时,将触发“保存密码”。所以我们只需要使用

$('#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.

someFunctionForLogin()执行ajax登录并重新加载/重定向到登录页面,同时event.preventDefault()由于提交表单而阻止原始重定向。

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.

如果你只处理 Firefox,上面的解决方案就足够了,但它在 Chrome 27 中不起作用。 然后你会问如何在 Chrome 27 中触发“保存密码”。

For Chrome 27, 'Save password' is triggered afterit 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

对于Chrome 27,通过提交包含属性 name='username' 的输入文本字段和属性 name='password ' 的输入密码字段的表单重定向到页面,将触发“保存密码”。因此,我们不能因为提交表单而阻止重定向,但我们可以在完成 ajax 登录后进行重定向。(如果您希望ajax登录不重新加载页面或不重定向到页面,不幸的是,我的解决方案不起作用。)然后,我们可以使用

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

带有 type='button' 的按钮将使单击按钮时不提交表单。然后,绑定一个函数到ajax登录按钮。最后,调用$('#loginForm').submit();重定向到登录页面。如果登录页面是当前页面,那么您可以将“signedIn.xxx”替换为当前页面以进行“刷新”。

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

现在,您会发现 Chrome 27 的方法也适用于 Firefox 21。所以最好使用它。

2. Restore the saved username/password:

2. 恢复保存的用户名/密码:

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.

如果您已经将 loginForm 硬编码为 HTML,那么您将发现在 loginForm 中恢复保存的密码没有问题。
但是,如果使用js/jquery动态制作loginForm,保存的用户名/密码将不会绑定到loginForm,因为保存的用户名/密码只有在文档加载时才绑定。
因此,您需要将 loginForm 硬编码为 HTML 并使用 js/jquery 动态移动/显示/隐藏 loginForm。



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

备注:如果你做ajax登录,不要添加autocomplete='off'像这样的标签形式

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

autocomplete='off'将导致将用户名/密码恢复到 loginForm 失败,因为您不允许它“自动完成”用户名/密码。

回答by spetson

Using a buttonto login:

使用按钮登录:

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

如果您使用type="button"带有onclick处理程序的 登录 using ajax,则浏览器将不会提供保存密码的服务。

<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 buttonand has no action field, the browser will not offer to save the password.

由于此表单没有提交按钮且没有操作字段,因此浏览器不会提供保存密码的功能。



Using a submitbutton to login:

使用提交按钮登录:

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

但是,如果您将按钮更改为type="submit"并处理提交,则浏览器将提供保存密码。

<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 Javascriptused in both methods:

这是两种方法中使用的Javascript

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
}

回答by TK421

I have been struggling with this myself, and I finally was able to track down the issue and what was causing it to fail.

我自己一直在努力解决这个问题,我终于能够追踪问题以及导致它失败的原因。

It all stemmed from the fact that my login form was being dynamically injected into the page (using backbone.js). As soon as I embed my login form directly into my index.html file, everything worked like a charm.

这一切都源于我的登录表单被动态注入页面(使用backbone.js)这一事实。一旦我将我的登录表单直接嵌入到我的 index.html 文件中,一切都像魅力一样。

I think this is because the browser has to be aware that there is an existing login form, but since mine was being dynamically injected into the page, it didn't know that a "real" login form ever existed.

我认为这是因为浏览器必须知道存在一个现有的登录表单,但由于我的正在动态注入页面,因此它不知道“真正的”登录表单曾经存在过。

回答by Vincent

This solution worked for me posted by Eric on the codingforums

这个解决方案对我有用,由 Eric 在codingforum 上发布



The reason why it does not prompt it is because the browser needs the page to phyiscally to refresh back to the server. A little trick you can do is to perform two actions with the form. First action is onsubmit have it call your Ajax code. Also have the form target a hidden iframe.

之所以不提示,是因为浏览器需要页面物理刷新回服务器。您可以做的一个小技巧是对表单执行两个操作。第一个动作是 onsubmit,让它调用你的 Ajax 代码。还让表单目标是一个隐藏的 iframe。

Code:

代码:

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

See if that causes the prompt to appear.

看看是否会导致出现提示。

Eric

埃里克



Posted on http://www.codingforums.com/showthread.php?t=123007

发表于http://www.codingforums.com/showthread.php?t=123007

回答by Michal Roharik

There's an ultimatesolution to force all browsers (tested: chrome 25, safari 5.1, IE10, Firefox 16) to ask for save the password using jQueryand ajaxrequest:

有一个终极解决方案可以强制所有浏览器(测试:chrome 25、safari 5.1、IE10、Firefox 16)使用jQueryajax请求保存密码:

JS:

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:

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>

The trick is in stopping the form to submit its own way (event.stopPropagation()), instead send your own code ($.ajax()) and in the ajax's success callback submit the form again so the browser catches it and display the request for password save. You may also add some error handler, etc.

诀窍是停止表单以自己的方式提交(event.stopPropagation()),而是发送您自己的代码($.ajax())并在 ajax 的成功回调中再次提交表单,以便浏览器捕获它并显示要求保存密码。您还可以添加一些错误处理程序等。

Hope it helped to someone.

希望它对某人有所帮助。

回答by w00t

I tried spetson's answerbut 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):

我尝试了spetson 的答案,但这在 Chrome 18 上对我不起作用。 有效的是向 iframe 添加加载处理程序而不中断提交(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:

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

getSessions() 执行 AJAX 调用并在失败时显示 loginForm div。(如果用户未通过身份验证,Web 服务将返回 403)。

Tested to work in FF and IE8 as well.

测试也适用于 FF 和 IE8。

回答by bta

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?

浏览器可能无法检测到您的表单是登录表单。根据上一个问题中的一些讨论,浏览器会查找看起来像<input type="password">. 您的密码表单字段是否与此类似?

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.

编辑:为了回答您在下面的问题,我认为 Firefox 通过form.elements[n].type == "password"(遍历所有表单元素)来检测密码,然后通过向后搜索密码字段之前的文本字段的表单元素来检测用户名字段(更多信息在这里)。据我所知,您的登录表单必须是 a 的一部分,<form>否则 Firefox 将无法检测到它。

回答by Danny Wave

Simple 2020 aproach

简单的 2020 年方法

This will automatically enable autocomplete and save password in browsers.

这将自动启用自动完成并在浏览器中保存密码。

  • autocomplete="on"(form)
  • autocomplete="username"(input, email/username)
  • autocomplete="current-password"(input, password)
  • autocomplete="on"(形式)
  • autocomplete="username"(输入,电子邮件/用户名)
  • autocomplete="current-password"(输入密码)
<form autocomplete="on">
  <input id="user-text-field" type="email" autocomplete="username"/>
  <input id="password-text-field" type="password" autocomplete="current-password"/>
</form>

Check out more at Apple's documentation: Enabling Password AutoFill on an HTML Input Element

在 Apple 的文档中查看更多信息: 在 HTML 输入元素上启用密码自动填充

回答by captainclam

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.

我花了很多时间阅读这个线程上的各种答案,而对我来说,它实际上略有不同(相关但不同)。在 Mobile Safari(iOS 设备)上,如果页面加载时登录表单为 HIDDEN,则不会出现提示(显示表单后提交)。您可以使用以下代码进行测试,该代码会在页面加载 5 秒后显示表单。删除 JS 和 display: none 就可以了。我还没有找到解决方案,只是发布以防其他人有同样的问题并且无法找出原因。

JS:

JS:

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

HTML:

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>

回答by David Rettenbacher

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
  • Chrome 39.0.2171.99m:工作中
  • Android Chrome 39.0.2171.93:运行中
  • Android 股票浏览器(Android 4.4):不工作
  • Internet Explorer 5+(模拟):工作
  • Internet Explorer 11.0.9600.17498 / 更新版本:11.0.15:正在运行
  • Firefox 35.0:工作

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

JS-小提琴: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.AutoCompleteSaveFormis needed
  • Internet Explorer need a "password"-fieldto show the store-password-dialog
  • Internet Explorer seems to require a click on submit-button(even if it's a fake click)
  • 对于动态登录表单,window.external.AutoCompleteSaveForm需要 调用
  • Internet Explorer需要一个“密码”字段来显示存储密码对话框
  • Internet Explorer 似乎需要点击提交按钮(即使是虚假点击)

Here is a sample ajax login-code:

这是一个示例 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
    });
};

Remarks

评论

  • "account/login" sets a cookieif 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.
  • 如果成功,“帐户/登录”设置一个cookie
  • 页面重定向(由 js 代码“手动”启动)似乎是必需的。我还测试了 iframe-post,但我没有成功。