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

这与我在这里问的问题有关: 如何让浏览器提示保存密码?

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

这是非常令人沮丧的,因为Firefox(以及其他大多数现代浏览器,我希望以类似的方式工作)的这个function似乎是一个谜。 这就像浏览器的一个魔术,它看你的代码,或者你提交什么,或者是什么东西,如果它看起来像一个带有用户名(或者电子邮件地址)字段和密码字段的login表单,它提供保存。

除了在这种情况下,在使用我的login表单之后没有向用户提供这个选项的情况下,这使我变得疯狂。 🙂

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

我的问题

Firefox使用何种启发式知道何时应该提示用户保存? 这不应该太难回答,因为它就在Mozilla的源代码中(我不知道该去哪里看,否则我会试着自己去挖掘它)。 我也没有find一个博客文章或从Mozilla开发者关于这一点的其他类似的开发人员的笔记运气。

(我可以很好地回答这个问题,Safari或IE浏览器;我会想象所有的浏览器用户非常相似的规则,所以如果我能得到它在其中之一工作,它将在其他工作。

(*请注意,如果您对我的回答与Cookie,encryption或其他任何有关如何将密码存储在本地数据库中的内容有关,那么您很可能误解了我的问题。

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

从我所知道的,你的login表单需要成为<form>一部分,否则Firefox将无法检测到它。 在你的密码字段上设置id="password"可能不会伤害任何一个。

如果这仍然给你很多问题,我会build议询问一个Mozilla项目的开发者邮件列表(你甚至可以得到devise该function的开发者的响应)。

我有同样的问题,并find了解决办法:

  1. 为了使浏览器要求存储密码,用户名和密码框必须在一个表格中,并且该表格必须实际提交。 提交button可以从onclick处理程序返回false(所以提交并不实际发生)。

  2. 为了使浏览器恢复以前存储的密码,input框必须存在于主HTML表单中,而不是通过JavaScriptdynamic创build。 表单可以用display:none来创build。

需要注意的是,密码是在页面加载时立即填充的,并且在整个会话期间存在,所以可以通过注入javascript来读取密码:这使得这种攻击更加糟糕。 为了避免这种情况,转发到一个单独的页面只是为了login是合理的,它解决了你开始阅读本主题的所有问题:)。 作为部分解决scheme,我在提交表单时清除了这些字段 – 如果用户注销并希望再次login,则密码不会被浏览器填充,但这对我来说不重要。

Viliam


你应该看看Mozilla的密码pipe理器debugging页面和nsILoginManager文档的扩展编写器(只是为了了解Firefox如何处理密码pipe理的技术细节)。 你可以挖掘到那里的答案和其他网页链接,以找出更多比你可能想知道密码pipe理器如何与网站和扩展互动。

(具体如在密码pipe理器debugging文档中指出的,确保你没有在你的html中closures自动完成,因为这将抑制提示保存用户名和密码)

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

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

这需要添加到页面。 它不能dynamic添加。 窗体和iframe可以设置为显示:无。 如果您没有设置iframe的src,那么在您提交表单至less一次之前不会显示提示。

然后调用表单submit():

 bridgeForm.submit(); 

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

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

所以这:

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

不是这个:

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

为angular色,铬,火狐工作:(我已经search了几个小时的testing – 铬forms的行动参数“#”是答案。1.21 @ gigawatts – 谢谢你!!!)

angular1.2.18

firefox 30.0 – 不需要隐藏表单提交,但需要“login-form-autofill-fix”指令fpr来识别自动填充的凭证

铬35.0 – 不需要指令,但隐形和“真实”的提交。

隐藏forms:

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

形成:

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

angular度指令(使用jqLit​​e):

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

修正: – 经过一些testing,我意识到,铬需要一点点超时我的angular度login方法(200毫秒) – 看来,redirect有时只是密码pipe理器太快。 – 更好地清除浏览器caching…随着每一个变化

那么,在我们的网站上 ,一个名为“用户名”的表单字段键入“文本”紧跟着一个名为“密码”和types“密码”的字段似乎是伎俩。

如果您使用AJAXlogin,请查看该源代码: https : //gist.github.com/968927

它包括提交login表单到隐藏的iframe,以便IE和Chrome可以检测到实际login,而不必重新加载页面。

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

我想它认为login操作失败,从而拒绝存储无效的凭据。

在Chrome 34.0上看到。

启发式法非常简单:按特定顺序检测具有特定名称的字段。 哪些,我不能告诉,但这对我和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. 

我build议看看Firefox的源代码。 这可能听起来比它的价值更麻烦,但它实际上是非常简单的代码。

https://dxr.mozilla.org/mozilla-central/source/toolkit/components/passwordmgr/LoginManagerContent.jsm

你想看的方法是_onFormSubmit_getFormFields_getPasswordFields

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

主要关键字在这里,

  <input type="password">