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

Posted

技术标签:

【中文标题】如何让浏览器提示保存密码?【英文标题】:How can I get browser to prompt to save password? 【发布时间】:2011-01-23 20:24:46 【问题描述】:

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

    用户点击“登录” 登录表单 html 使用 AJAX 加载并显示在页面的 DIV 中 用户在字段中输入用户/密码并单击提交。这不是<form>——用户/通行证是通过 AJAX 提交的 如果用户/密码正常,页面会在用户登录后重新加载。 如果用户/密码错误,页面不会重新加载,但 DIV 中会出现错误消息,用户可以重试。

问题是:浏览器从不提供通常的“保存此密码?是/从不/现在不”提示,它为其他网站提供。

我尝试用“autocomplete='on'”将<div> 包装在<form> 标签中,但这并没有什么不同。

是否可以让浏览器提供存储密码而无需对我的登录流程进行重大修改?

谢谢 埃里克

附言补充一下我的问题,我肯定在使用存储密码的浏览器,而且我从来没有点击过“从不访问这个网站”......这是一个技术问题,浏览器没有检测到它是一个登录表单,而不是操作员错误:-)

【问题讨论】:

不要忘记不是所有的浏览器都可以存储密码。 可能是浏览器提供来保存您的用户/通行证,然后您点击了“不再询问!” ? 相关:***.com/questions/6142725/… 【参考方案1】:

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

有两件事要知道:

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

1。触发“保存密码”:

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

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

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

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

对于 Chrome 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>

type='button' 的Button 将使单击该按钮时不提交表单。 然后,将函数绑定到 ajax 登录按钮。最后,调用$('#loginForm').submit(); 会重定向到登录页面。如果登录页面是当前页面,则可以将'​​signedIn.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 失败,因为您不允许它“自动完成”用户名/密码。

【讨论】:

在 Chrome 中,'event.preventDefault()' 会阻止显示“保存密码”提示,请参阅此错误:code.google.com/p/chromium/issues/detail?id=282488 对于其他偶然发现此问题的人,我认为他们正在为此发布修复程序:code.google.com/p/chromium/issues/detail?id=357696 很多用户使用ENTER 键提交表单,因为您在用户提交表单时有prevented default,所以什么都不会发生,这是糟糕的用户体验。提交时可以检查回车键keycode,但是会再次进入乞讨... Chrome 46 修复了它的错误行为 - 不再需要变通方法。见***.com/a/33113374/810109 运行不可靠,如果您从 javascript 提交,某些浏览器不会触发“记住”功能。【参考方案2】:

使用按钮登录:

如果您使用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

【讨论】:

@Bigood 因为它有效,而接受的答案却没有(至少对我而言)。谢谢斯佩森! 在 IE 中也适用于我。我现在可以吻你了! 也为我工作.. :) 这是正确的,也是解决问题最优雅的方法。 之所以有效,是因为我只需复制第二个代码并通过检查元素将其粘贴到登录页面,在该页面上新添加的字段中输入用户名/密码并按登录,然后它会提示我保存用户/密码.然后我刷新页面,瞧,它提示我选择已经保存的用户/密码;)【参考方案3】:

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

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

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

【讨论】:

从 Chrome 版本 46 开始,您现在还可以动态注入表单,它们将被识别为可以保存凭据的“真实”登录表单。见***.com/a/33113374/810109【参考方案4】:

Eric 在codingforums 上发布的这个解决方案对我有用


之所以没有提示是因为浏览器需要页面物理刷新到服务器。您可以做的一个小技巧是对表单执行两个操作。第一个动作是 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

【讨论】:

作为说明,我发现如果表单是 submitted to itself,Chrome 11 不会提供保存您的凭据。所以你需要将action 设置为一些虚拟页面。 这将在 url 中发送密码明文作为获取请求。如果方法更改为 POST,Firefox (16) 将在新选项卡中打开以前隐藏的框架。 android 4 上的 chrome 也是如此。:-( Chrome 46 修复了它的错误行为 - 不再需要 iframe 变通方法。见***.com/a/33113374/810109【参考方案5】:

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

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 的成功回调中再次提交表单以便浏览器捕获它并显示密码保存请求。 您还可以添加一些错误处理程序等。

希望对某人有所帮助。

【讨论】:

这实际上会对login.php?username=username&amp;password=password 进行 HTTP 访问,这首先会破坏保存密码的全部目的 Woooooooooooooooooooooooooooooooooooooooooooooh !这对我有用;)非常感谢! 是的,添加event listener 并添加event.preventDefault() 加上event.stopPropagation()【参考方案6】:

简单的 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 的文档中查看更多信息: Enabling Password AutoFill on an HTML Input Element

【讨论】:

仅供参考,这似乎需要提交表单(不能使用 XHR 和preventDefault),如果只有一个密码字段(数字安全类型的应用程序),它将不起作用。将这些发现分享给其他可能觉得有用的人。【参考方案7】:

我尝试了spetson's answer,但这对我在 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)返回一些文本或其他可见内容,否则它不会起作用。 Chrome 46 修复了它的错误行为 - 不再需要 iframe 变通方法。见***.com/a/33113374/810109【参考方案8】:

浏览器可能无法检测到您的表单是登录表单。根据this previous question 中的一些讨论,浏览器会查找类似于&lt;input type="password"&gt; 的表单字段。您的密码表单字段是否与此类似?

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

【讨论】:

很相似,是的,谢谢,我会接受这个作为官方答案,因为这与我们得到的差不多。令人沮丧的是:我似乎(在网络上的任何地方)都找不到一篇简单的博客文章,上面写着“这是浏览器用来检测您填写的表单是否是登录表单的规则,因此他们可以提供保存用户的密码。”考虑到这有点黑魔法(至少考虑到 Mozilla 是开源的),你会认为有人会发布启发式方法。 (同样,我似乎没有办法“提示”我的登录表单,所以浏览器知道它是一个登录表单。再一次,很惊讶这没有更好地记录在那里在网络上。我认为我的更改将是表单字段名称和整体 HTML 结构,然后我希望 [!] 可以解决问题。) 好吧,不走运。我从一个稍微不同的角度提出了一个新问题:***.com/questions/2398763/…【参考方案9】:

没有一个答案表明您可以使用 HTML5 History API 提示保存密码。

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

您可以在此处找到自动完成值的列表: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/en-US/docs/Web/API/History/pushState

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

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

【讨论】:

这是 2020 年的答案!我不得不使用history.pushState(, null "Your new page title"); 来更改网址,而无需任何导航【参考方案10】:

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

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>

【讨论】:

【参考方案11】:

以下代码在

上测试 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/

邮编:

// modified post-code from https://***.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

备注

对于动态登录表单,需要调用 window.external.AutoCompleteSaveForm Internet Explorer 需要一个“密码”字段来显示商店密码对话框 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
    );
;

备注

"account/login" 如果成功则设置 cookie 页面重定向(由js代码“手动”启动)似乎是必需的。我还测试了一个 iframe-post,但没有成功。

【讨论】:

【参考方案12】:

我为 Prototype.JS 用户找到了一个相当优雅的解决方案(或 hack,任何合适的),它是最后一个使用 Prototype 的人。相应的 jQuery 方法的简单替换应该可以解决问题。

首先,确保有一个&lt;form&gt; 标记,以及一个带有类名的提交按钮,该按钮可以稍后引用(在本例中为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 中运行。

【讨论】:

【参考方案13】:

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

【讨论】:

【参考方案14】:

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

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

例如

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

【讨论】:

【参考方案15】:

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

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

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

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

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

不会提供在 IE 中保存密码(尽管它已在其他浏览器中工作)。

【讨论】:

【参考方案16】:

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

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

希望这可以是暗示性的。 :-)

【讨论】:

我不会将用户信息存储在 cookie 中,至少不会存储任何敏感信息。 我不是说要存储用户密码。显然,您必须非常有创意地创建useful garbage 来识别用户信息。甚至 SO 也将信息存储在 cookie 中以识别您。 很公平,但我仍然会尽可能多地加密。 @JackMarchetti 在客户端对其进行加密将是一个糟糕(而且有点无用)的想法。由于需要加密的代码是可见的,因此任何人都可以找到 .js 文件并对其进行解密。这意味着您不应将数据存储在 cookie 中【参考方案17】:

事实是,您不能强迫浏览器询问。我确信浏览器有它自己的算法来猜测你是否输入了用户名/密码,例如寻找type="password" 的输入,但你不能设置任何东西来强制浏览器。

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

【讨论】:

我说要加密存储在其中的任何内容。 饼干?这是一个等待发生的坏主意【参考方案18】:

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

【讨论】:

【参考方案19】:

这对我来说效果更好,因为它是 100% ajaxed 并且浏览器会检测到登录。

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

【讨论】:

【参考方案20】:

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

你可以有一个“还记得我吗?”复选框并让表单创建一个cookie来存储//用户的登录信息//信息。 编辑:用户会话信息

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

【讨论】:

以上是关于如何让浏览器提示保存密码?的主要内容,如果未能解决你的问题,请参考以下文章

火狐浏览器。登录网站时提示是不是保存密码,我点了不再提醒,现在想保存了,不提示了怎么搞?

浏览器如何知道何时提示用户保存密码?

网页怎么保存密码 怎么让网页记住密码

怎么记住登录过的网页账号密码?

如何让浏览器保存密码而不重定向?

怎么记住密码