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

时间:2010-03-08 01:16:04

标签: firefox browser login

这与我在这里提出的问题有关: How can I get browser to prompt to save password?

这是问题:我无法让我的浏览器提示我保存我正在开发的网站的密码。 (我在谈论有时当你在Firefox上提交表单时出现的栏,上面写着“记住yoursite.com的密码?是/现在/从不”)

这非常令人沮丧,因为Firefox(以及大多数其他现代浏览器,我希望以类似方式工作)的这一功能似乎是一个谜。这就像浏览器所做的一个神奇技巧,它会查看您的代码,或者您提交的内容,或者某些东西,如果它“看起来”像一个带有用户名(或电子邮件地址)字段和密码字段的登录表单,它提供保存。

除非在这种情况下,在使用我的登录表单后它没有向我的用户提供该选项,这让我很疯狂。 : - )

(我检查了我的Firefox设置 - 我没有告诉浏览器“从不”这个网站。它应该是提示。)

我的问题

Firefox使用什么启发式来了解何时应该提示用户保存?这应该不难回答,因为它就在Mozilla源代码中(我不知道在哪里看,否则我会尝试自己挖掘它)。我也没有幸运地从Mozilla开发者那里找到关于此的博客文章或其他类似的开发者说明。

(我会很好地回答Safari或IE这个问题;我会想象所有浏览器都使用非常相似的规则,所以如果我能在其中一个中使用它,那么它将适用于其他浏览器。)

(*请注意,如果您对我的回答与cookie,加密或其他任何关于我如何在我的本地数据库中存储密码的事情有关,那么您误解我的问题的可能性很大。:-)

13 个答案:

答案 0 :(得分:51)

根据我所读到的内容,我认为Firefox会通过form.elements[n].type == "password"检测密码(遍历所有表单元素),然后通过在密码字段之前的文本字段的表单元素向后搜索来检测用户名字段(更多信息here)。你可以在Javascript中尝试类似的东西,看看你是否可以检测到你的密码字段。

据我所知,您的登录表单需要成为<form>的一部分,否则Firefox将无法检测到它。在密码字段中设置id="password"可能也不会有任何损害。

如果这仍然给你带来很多问题,我建议你询问一下Mozilla项目的开发者邮件列表(你甚至可能会得到设计该功能的开发者的回复)。

答案 1 :(得分:17)

我遇到了同样的问题并找到了解决方案:

  1. 要使浏览器要求存储密码,用户名和密码框必须是一个表格,并且该表格必须实际提交。提交按钮可能会从onclick处理程序返回false(因此提交实际上不会发生)。

  2. 要使浏览器恢复以前存储的密码,输入框必须存在于主HTML表单中,而不是通过javascript动态创建。可以使用display:none。

  3. 创建表单

    需要注意的是,密码在页面加载后立即填充并在整个会话期间出现在那里,因此可以通过注入的javascript读取:它使这种攻击更加糟糕。为避免这种情况,转发到单独的页面只是为了登录是合理的,它解决了您开始阅读本主题的所有问题:)。作为部分解决方案,我在提交表单时清除字段 - 如果用户注销并想再次登录,则密码不会被浏览器填写,但这对我来说很小。

    Viliam


答案 2 :(得分:10)

您应该查看Mozilla Password Manager Debugging页面和nsILoginManager docs的扩展编写者(仅适用于Firefox如何处理密码管理的详细技术细节)。您可以深入了解那里的答案以及链接到那里的其他页面,以了解更多您可能想知道密码管理器如何与站点和扩展进行交互。

(特别是在密码管理器调试文档中指出,请确保您的html中没有自动完成设置为off,因为这将禁止保存用户名和密码的提示)

答案 3 :(得分:6)

这似乎适用于Mac上的Firefox,Chrome和Safari。未在Windows上测试过。

<form id="bridgeForm" action="#" target="loginframe" autocomplete="on">
    <input type="text" name="username" id="username" />
    <input type="password" name="password" id="password"/>
</form>

<iframe id="loginframe" name="loginframe" src="anyblankpage.html"></iframe>

这需要添加到页面中。它无法动态添加。表单和iframe可以设置为display:none。如果您没有设置iframe的src,则在您提交表单至少一次之前,提示将不会显示。

然后调用表单submit():

bridgeForm.submit();

该操作可以是可选的,自动完成可以是可选的。没有测试过。

注意:在某些浏览器上,在浏览器响应之前,表单必须在服务器(而不是localhost而不是文件系统)上运行。

所以这个:

http://www.mysite.com/myPage.html

不是这个:

http://126.0.0.1/myPage.html
http://localhost/myPage.html
file://directory/myPage.html

答案 4 :(得分:6)

使用angular,chrome,firefox为我工作:(我已经搜索并测试了几个小时 - 对于chrome,表单操作参数(#)就是答案。@1.21 gigawatts,谢谢!!!你的answer非常宝贵。)

形式

firefox 30.0 - 不需要隐藏的iframe和提交按钮(如下所示),但需要&#34; login-form-autofill-fix&#34;用于识别自动填充凭证的指令,如下所示:

<form name="loginForm" login-form-autofill-fix action="#" target="emptyPageForLogin" method="post" ng-submit="login({loginName:grpEmail,password:grpPassword})">
<input type="text" name=username" id="username" ng-model="grpEmail"/>
<input type="password" name="password" id="password" ng-model="grpPassword"/>
<button type="submit">Login</button>
</form>

隐藏的iframe

chrome 35.0 - 不需要上述指令,但需要隐藏的iframe和真实表单上的提交按钮。隐藏的iframe看起来像

<iframe src="emptyPageForLogin.html" id="emptyPageForLogin" name="emptyPageForLogin" style="display:none"></iframe>

angular指令(使用jqLit​​e)

这适用于角度1.2.18

module.directive('loginFormAutofillFix', function() { 
            return function(scope, elem, attrs) {
        if(!attrs.ngSubmit) {
            return;
        }
        setTimeout(function() {
            elem.unbind("submit").bind("submit", function(e) {
                //DO NOT PREVENT!  e.preventDefault(); 
                elem.find("input").triggerHandler("input");
                scope.$apply(attrs.ngSubmit);
            });
        }, 0);
});

修正案

  • 经过一些测试后,我意识到,Chrome通过角度登录方法(200ms)需要稍微超时 - 看起来,重定向有时对于密码管理器来说太快了。
  • 更好地清除browsercache ......每次更改

答案 5 :(得分:3)

好吧,在our site上,名称为“username”的表单字段键入“text”后紧跟一个名为“password”并输入“password”的字段,似乎可以解决问题。

答案 6 :(得分:3)

如果您正在使用AJAX登录,请查看该源代码:https://gist.github.com/968927

它包括向隐藏的iframe提交登录表单,以便IE和Chrome可以检测实际登录,而无需重新加载页面。

答案 7 :(得分:3)

我还注意到,如果登录表单在登录请求后仍然存在,Chrome将不会记住密码,即使它隐藏在页面上也是如此。

我猜它认为登录操作失败,因此拒绝存储无效凭证。

在Chrome 34.0上看到。

答案 8 :(得分:3)

我建议您查看Firefox source code。这实际上非常简单。

您要查看的方法是_onFormSubmit_getFormFields_getPasswordFields

您甚至可能会发现您遇到的问题实际上是Firefox中未被发现的错误;)https://bugzilla.mozilla.org/show_bug.cgi?id=1211780

答案 9 :(得分:2)

这里的启发式非常简单:以特定顺序检测具有某些名称的字段。哪些,我不知道,但在Chrome和IE中这对我来说很好:

Username field: name "login", type "text";
Password field: name "password", type "password"
Submit button: element "input", type "submit". 
Element "button" type "submit" did not work.

答案 10 :(得分:1)

如果您在输入type = password之前在表单中有两个type = text, 浏览器检测最近的输入类型=用户名的文本。

这不是另一个输入是= username和name = username

要解决此问题,您必须在输入密码之前准确输入要保存的用户名

祝你好运: - )

答案 11 :(得分:0)

除了已经说过的很多内容之外,我还意识到输入字段不能被“禁用”。我们有一个多步登录,首先要求输入用户名,然后在下一个屏幕上输入密码。在第二个屏幕上,我们重复了电子邮件但禁用了它,这阻止了Chrome等。人。从识别为用户名的有效字段。

由于我们真的想保留那个禁用的输入字段,我们最终得到了这个hacky解决方法:

<input type="text" name="display-username" id="display-username" value="ENTERED_USERNAME" placeholder="Username" disabled="disabled">
<input type="text" name="username" id="username" value="ENTERED_USERNAME" placeholder="Username" style="display: none;">
<input type="password" name="password" id="password" value="" autofocus="autofocus" autocomplete="on" placeholder="Password" required="required">

我不会推荐这么做,但也许它会在某人的代码中指出某些事情:

  1. 第一个元素在禁用的输入字段中显示用户名。禁用不会作为表单的一部分提交,并且浏览器无法识别已禁用。
  2. 第二个元素是一个正确的输入字段,type =“text”和name / id =“username”。这被浏览器识别。为了防止用户编辑它,我们用CSS(display:none)隐藏它。

答案 12 :(得分:-1)

主要关键字在这里,

   <input type="password">