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


149

嘿,我正在使用一个具有如下登录对话框的Web应用程序:

  1. 用户点击“登录”
  2. 登录表单HTML随AJAX一起加载,并在第DIV页上显示
  3. 用户在字段中输入用户/密码,然后单击提交。不是<form>-用户/密码通过AJAX提交
  4. 如果用户/密码正确,则页面将在用户登录后重新加载。
  5. 如果用户/密码不正确,则不会重新加载页面,但DIV中会显示错误消息,并且用户可以重试。

这是问题所在:浏览器从不提供通常针对其他站点的“保存此密码?是/从不/不立即”提示。

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

是否可以让浏览器提供存储密码的功能而无需大量修改我的登录流程?

谢谢埃里克

ps添加到我的问题中,我肯定是与存储密码的浏览器一起工作,而且我从未单击过“从不访问此站点” ...这是浏览器无法检测到它是登录表单的技术问题,不是操作员错误:-)


不要忘记,并非所有浏览器都可以存储密码。
Buhake Sindi'3

1
可能是浏览器提供了保存您的用户名/通行证的功能,然后您单击了“不再询问!” ?
clyfe

Answers:


72

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

有两件事要知道:

  1. 触发“保存密码”,然后
  2. 恢复保存的用户名/密码

1.触发“保存密码”:

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

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

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

如果仅使用Firefox,上述解决方案就足够了,但在Chrome 27中不起作用。然后,您将询问如何在Chrome 27中触发“保存密码”。

对于铬27,“保存密码”被触发后,它被提交包含输入文本字段的形式重定向到页面属性名=“用户名”和密码输入字段属性名=“密码”。因此,由于提交表单,我们无法阻止重定向,但是我们可以在完成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'的Button将使单击按钮时不提交表单。然后,将功能绑定到按钮以进行ajax登录。最后,调用$('#loginForm').submit();将重定向到登录页面。如果登录页面是当前页面,则可以将“ signIn.xxx”替换为当前页面以进行“刷新”。

现在,您会发现Chrome 27的方法也可以在Firefox 21中使用。因此最好使用它。

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

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


备注: 如果您进行ajax登录,请不要autocomplete='off'以标签形式添加

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

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


2
在Chrome中,“ event.preventDefault()”阻止显示“保存密码”提示,请参见以下错误:code.google.com/p/chromium/issues/detail?
id=282488

对于其他偶然发现此问题的人,我认为他们正在为此发布修复程序:code.google.com/p/chromium/issues/detail?

2
许多用户都在使用ENTER密钥提交表单,因为您prevented default在用户提交表单时拥有任何东西,所以不会发生任何事情,这是不好的UX。您可以keycode在提交时检查回车键,但是您将再次遇到乞求...
David Reinberger 2015年

2
Chrome 46修复了错误的行为-不再需要任何解决方法。请参阅stackoverflow.com/a/33113374/810109
mkurz 2015年

1
无法可靠地运行,如果您从Javascript提交,某些浏览器不会触发“记住”功能。
JustAMartin

44

使用按钮登录:

如果您使用type="button"带有onclick处理程序的和来使用登录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>

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


使用提交按钮登录:

但是,如果将按钮更改为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>

使用此方法,浏览器应提供保存密码的功能。


这是两种方法中使用的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
}

1
@Bigood因为它在接受的答案无效的情况下起作用(至少对我而言)。谢谢斯佩森!
Double M

1
在IE中也对我有用。我现在可以吻你!
雷拉

1
也为我工作.. :)
Nabeel

1
这是正确的方法,也是解决问题的最优雅的方法。
Arash Kazemi

之所以起作用,是因为我只需复制第二个代码并通过inspect元素将其粘贴到登录页面中,在该页面上新添加的文件中输入用户名/密码,然后按登录,然后提示我保存用户/密码。然后刷新页面,瞧,它提示我选择已经保存的用户/密码;)
Dewlance

15

我一直在为此苦苦挣扎,终于找到了问题的根源以及导致它失败的原因。

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

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


从Chrome 46版开始,您现在还可以动态注入表单,这些表单将被识别为可以保存凭据的“真实”登录表单。请参阅stackoverflow.com/a/33113374/810109
mkurz 2015年

12

这个解决方案对我有用,由Eric在编码论坛上发布


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

码:

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

查看是否导致提示出现。

埃里克


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


5
值得注意的是,我发现如果将表单提交给自己,Chrome 11不会提供保存您的凭据的功能。因此,您需要设置action一些虚拟页面。
user123444555621 2011年

这将作为获取请求在URL中发送明文密码。如果方法更改为POST,则Firefox(16)将在新选项卡中打开以前隐藏的框架。android 4上的chrome也是如此::-(
stefan.s 2012年

Chrome 46修复了错误的行为-不再iframe需要任何解决方法。参见stackoverflow.com/a/33113374/810109
mkurz 2015年

10

这里有一个最终的解决方案,迫使所有浏览器(测试:铬25,Safari浏览器5.1,IE10,火狐16),要求保存密码使用的jQueryAJAX请求:

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>

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

希望它对某人有所帮助。


7
这实际上做一个HTTP GET到login.php?username=username&password=password其defats摆在首位保存密码的全部目的
Adaptabi

喔喔喔喔喔喔喔喔喔喔喔喔喔喔喔喔喔喔喔喔喔!这对我有用;)非常感谢!
Hardik Thaker 2014年

1
是的,添加event listener到表单中并添加event.preventDefault()加号event.stopPropagation()
Densi Tensy '16

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

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()进行AJAX调用,并在失败时显示loginForm div。(如果用户未通过身份验证,则Web服务将返回403)。

经测试也可以在FF和IE8中使用。


我在Chrome中尝试了此方法,除非操作页面(/login在您的示例中)返回了一些文本或其他可见内容,否则该方法将无法工作。
2014年

1
Chrome 46修复了错误的行为-不再iframe需要任何解决方法。参见stackoverflow.com/a/33113374/810109
mkurz 2015年

4

浏览器可能无法检测到您的表单是登录表单。根据对上一个问题的讨论,浏览器寻找如下形式的表单字段<input type="password">。密码表单字段的实现是否与此类似?

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


1
相似,是的,谢谢,我将其作为正式答案,因为这已经接近我们的预期了。令人沮丧的是:在网络上的任何地方,我似乎都找不到一个简单的博客文章,其中说:“这是浏览器用来检测您填写的表单是否为登录表单的规则,因此他们可以提供保存用户的密码。” 考虑到这有点不可思议(至少考虑到Mozilla是开源的),您可能会认为有人会发布启发式方法。
埃里克(Eric)2010年

(同样,我似乎也没有办法“提示”我的登录表单,因此浏览器知道这是一个登录表单。同样,令我感到惊讶的是,它并没有更好地记录在网络上。我认为我的更改是将涉及表单字段名称和整体HTML结构,然后希望[!]解决该问题。)
Eric 2010年

好吧,没有运气。我问了一个新问题,从一个稍微不同的角度解决了这个问题:stackoverflow.com/questions/2398763/…–
埃里克

3

简单的2020方法

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

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

在Apple文档中查看更多信息: 在HTML Input Element上启用密码自动填充


4
仅供参考,这似乎需要提交表单(不能使用XHR和preventDefault),如果只有一个密码字段(数字安全类型的应用程序),它将无法使用。与其他可能有用的人分享这些发现。
托马什Hübelbauer

2

我花了很多时间阅读此线程上的各种答案,对我而言,实际上是有些不同(相关但不同)。在Mobile Safari(iOS设备)上,如果在页面加载时登录表单为“隐藏”,则不会出现提示(在您显示表单然后提交后)。您可以使用以下代码进行测试,该代码在页面加载5秒后显示表格。删除JS和显示:无,并且可以使用。我还没有找到解决方案,只是在其他人遇到相同问题而又找不到原因的情况下发布。

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>

2

没有一个答案已经很清楚了,您可以使用HTML5历史记录API提示保存密码。

首先,您需要确保至少有一个 <form>带有密码和电子邮件或用户名字段元素。只要您使用正确的输入类型(密码,电子邮件或用户名),大多数浏览器都会自动处理此问题。但是请确保为每个输入元素正确设置自动完成值。

您可以在此处找到自动完成值的列表:https : //developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete

你需要的是:usernameemailcurrent-password

然后,您有两种可能性:

  • 如果提交后导航到其他URL,大多数浏览器将提示您保存密码。
  • 如果您不想重定向到其他URL,甚至不想重新加载页面(例如,单个页面应用程序)。只需在表单的提交处理程序中防止事件默认设置(使用e.preventDefault)即可。您可以使用HTML5历史记录API在历史记录中添加一些内容,以指示您已在单页应用程序中“导航”。现在,浏览器将提示您保存密码和用户名。
history.pushState({}, "Your new page title");

您也可以更改页面的URL,但这不是提示您保存密码所必需的:

history.pushState({}, "Your new page title", "new-url");

文档:https : //developer.mozilla.org/zh-CN/docs/Web/API/History/pushState

这样做还有一个好处,就是如果用户输入的密码不正确,您可以防止浏览器要求保存密码。请注意,在某些浏览器中,即使您调用.preventDefault并且不使用历史记录API,浏览器也会始终要求保存凭据。

如果您不想导航和/或修改浏览器历史记录,可以改用replaceState(这也可以)。


这是2020年的答案!我不得不使用history.pushState({}, null "Your new page title");url进行了更改,而没有任何导航
Delcon

1

以下代码已通过测试

  • 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小提琴:http
//jsfiddle.net/ocozggqu/

邮政编码:

// modified post-code from /programming/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
}

备注

  • 对于动态登录表单,window.external.AutoCompleteSaveForm需要 调用
  • Internet Explorer 需要一个“密码”字段来显示store-password-dialog
  • Internet Explorer似乎需要单击“提交”按钮(即使是假单击)

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

备注

  • 如果成功,“帐户/登录”设置cookie
  • 似乎需要页面重定向(由js代码“手动”启动)。我也测试了一个iframe-post,但是我没有成功。

1

我为Prototype.JS用户找到了一个相当优雅的解决方案(或破解方法),它是最后一次使用Prototype的方法之一。简单地替换相应的jQuery方法就可以解决问题。

首先,确保有一个<form>标签和一个提交按钮,其类名稍后可被引用(在本例中为faux-submit),该按钮嵌套在样式设置为的元素内display:none,如下所示:

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

然后为创建一个点击观察器button,它将“提交”表单,如下所示:

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

然后为submit事件创建一个侦听器,并停止它。event.stop()会停止DOM中的所有提交事件,除非它是用Event.findElement隐藏的输入按钮的类包装的(如上所示faux-submit):

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

经过测试,该软件可以在Firefox 43和Chrome 50中正常工作。


0

您的站点可能已经在列表中,告诉浏览器不要提示您保存密码。在firefox中,选项->安全->记住站点密码[复选框]-例外[按钮]


0

在@Michal Roharik的答案中添加更多信息。

如果您的ajax调用将返回返回URL,则应在调用form.submit之前使用jquery将表单操作属性更改为该URL。

例如

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

0

我有类似的问题,登录使用ajax完成,但是如果使用ajax提交表单(#loginForm),则浏览器(firefox,chrome,safari和IE 7-10)将不提供保存密码。

作为解决方案我向ajax提交的表单添加了隐藏的提交输入(#loginFormHiddenSubmit),并且ajax调用将返回成功后,我将触发单击以隐藏提交的输入。该页面需要刷新的任何方式。点击可以通过以下方式触发:

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

我添加隐藏的提交按钮的原因是:

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

不会提供在IE中保存密码的功能(尽管它已在其他浏览器中使用)。


-1

并非每个浏览器(例如IE 6)都具有记住凭证的选项。

您可以做的一件事是(一旦用户成功登录)通过cookie存储用户信息,并具有“在此计算机上记住我”选项。这样,当用户再次出现时(即使他已注销),您的Web应用程序也可以检索cookie并获取用户信息(用户ID +会话ID),并允许他/她继续工作。

希望这会有所启发。:-)


我不会将用户信息存储在Cookie中,至少不会存储任何敏感信息。
杰克·马尔凯蒂

我并不是要存储用户密码。显然,您将必须具有创造力useful garbage来识别用户信息。甚至SO也将信息存储在cookie中以便识别您。
Buhake Sindi'3

足够公平,但我仍然会尽力进行加密。
杰克·马尔凯蒂

@JackMarchetti对客户端进行加密将是一个坏主意(并且有点无用)。由于加密所需的代码是可见的,因此任何人都可以找到.js文件并将其解密。这意味着您不应该将数据存储在cookie中
Universal Electricity

-1

事实是,您不能强迫浏览器询问。我确定浏览器拥有自己的算法,可以猜测您是否输入了用户名/密码,例如寻找的输入,type="password"但您无法设置任何强制浏览器的内容。

正如其他人所建议的,您可以在cookie中添加用户信息。如果这样做,则最好至少对其进行加密,并且不要存储其密码。也许最多存储他们的用户名。


你建议饼干吗?
Buhake Sindi'3

我说要加密存储在其中的任何内容。
杰克·马尔凯蒂

1
饼干?那真是一个不好的主意,等待发生
NightSkyCode 2015年

-1

您可以将对话框附加到表单,因此所有这些输入都在表单中。另一件事是在用户名文本字段之后设置密码文本字段。


-1

这对我来说效果更好,因为它被100%取消,浏览器会检测到登录名。

<form id="loginform" action="javascript:login(this);" >
 <label for="username">Username</label>
 <input name="username" type="text" value="" required="required" />
 <label for="password">Password</label>
 <input name="password" type="password" value="" required="required" />
 <a href="#" onclick="document.getElementById("loginform").submit();"  >Login</a>
</form>

-2

使用Cookie可能是最好的方法。

您可以选中“记得我吗?”复选框。并让该表单创建一个Cookie,以存储//用户的登录信息。编辑:用户会话信息

要创建Cookie,您需要使用PHP处理登录表单。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.