ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

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

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

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

我的问题

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

(我可以为 Safari 或 IE 回答这个问题;我想所有的浏览器都使用非常相似的规则,所以如果我可以让它在其中一个中工作,它会在其他浏览器中工作。)

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

我不知道。您的表单是带有密码类型字段的 POST 表单吗?
是的,包裹在
标签中,字段名为“用户名”和“密码”。我使用 AJAX 将它作为一个单独的层加载,但 disqus.com 也是如此(只是举一个例子),它对他们非常有用。这就是为什么,而不是(继续)随机调整事物以查看它是否有帮助,我想确切地了解浏览器的想法。

A
Ariel

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

据我所知,您的登录表单必须是 <form> 的一部分,否则 Firefox 不会检测到它。在您的密码字段上设置 id="password" 可能也不会受到伤害。

如果这仍然给您带来很多问题,我建议您在 Mozilla 项目的开发人员邮件列表之一上提问(您甚至可能会收到设计该功能的开发人员的回复)。


这太棒了。谢谢。这就是我要找的。
这帮助我让它在 Firefox 中工作,但我对 Chrome 没有任何运气。这是我正在使用的表单:
@1.21gigawatts- 没有“标准”方式来做到这一点(据我所知),所以不同的浏览器可能会略有不同。我不知道 Chrome 的流程与 Firefox 的流程有何不同,但如果您查看 Chrome 源代码,您可能会弄清楚。我知道 Firefox 是如何做到这一点的唯一方法是阅读他们的代码。这是有人需要在大图表中记录的那种事情,列出每个浏览器是如何做到的......
密码管理器代码的作者在 2013 年的一篇博文中向您介绍了一些事情——值得一读:blog.mozilla.org/dolske/2013/08/20/on-firefoxs-password-manager
更新了密码管理器博客文章的链接:dolske.wordpress.com/2013/08
u
user324356

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

要让浏览器要求存储密码,用户名和密码框必须在表单中,并且必须实际提交该表单。提交按钮可能会从 onclick 处理程序返回 false(因此实际上不会发生提交)。为了使浏览器恢复之前存储的密码,输入框必须存在于主 HTML 表单中,而不是通过 javascript 动态创建。可以使用 display:none 创建表单。

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

维利亚姆


适用于 Firefox 3.5 和 IE8,不适用于 Chrome(第 1 点不起作用)。也许提交必须是真实的......
user324356 - 我将表单设置为“#”,然后调用 myForm.submit(),这在 Firefox 中有效,但 Chrome 没有提示。
仅供参考:当您使用 return falseevent.preventDefault() 时,由于以下错误,这将无法在 Chrome 中运行:code.google.com/p/chromium/issues/detail?id=282488
这对于firefox当前使用的算法来说绝对重要——它不是密码管理器“寻找”的唯一东西,但firefox密码管理器不会在没有实际提交的情况下被触发。
更新:Chrome 46 修复了它的错误行为——现在一切正常。请参阅stackoverflow.com/a/33113374/810109
j
jpaugh

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

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


1
1.21 gigawatts

这似乎适用于 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,则在您至少提交一次表单之前不会显示提示。

然后调用表单提交():

bridgeForm.submit();

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

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

所以这:

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

不是这个:

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


@ErikAronesty 你有没有想出一个解决方案?我注意到在某些浏览器(safari)中,页面必须在服务器上,而不是本地主机或文件系统上。
Chrome 46 修复了它的错误行为 - 不再需要 iframe 变通方法。请参阅stackoverflow.com/a/33113374/810109
j
jpaugh

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

形式

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

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

角度指令(使用 jqLite)

这适用于角度 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 需要通过角度登录方法(200 毫秒)稍微超时 - 看起来,重定向有时对于密码管理器来说太快了。

更好地清除浏览器缓存...每次更改


由于最新的 chrome,pw-manager 仅有时填写表格。密码管理器有时会弹出,有时不会...现在似乎是一个随机功能。
新的 Firefox 会忽略自动填充的密码字段。 triggerHandler("input") 不工作。这可以通过本机事件 (document.createEvent) 解决 - 将其分派一次火灾。
Chrome 46 修复了它的错误行为 - 不再需要 iframe 变通方法。请参阅stackoverflow.com/a/33113374/810109
@110maor 我花了很长时间才理解你的帖子。我希望我的编辑符合您的意图。
s
spender

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


对我来说太快了!我的想法完全...(我正在删除我的答案)
是的。试过了。没运气。 :-( 我的理论是我的页面上有浏览器不喜欢的其他内容/使它认为该页面没有登录表单......
A
Adrien Joly

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

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


Chrome 46 修复了它的错误行为 - 不再需要 iframe 变通方法。请参阅stackoverflow.com/a/33113374/810109
j
jonsca

这里的启发式方法非常简单:以特定顺序检测具有特定名称的字段。哪些,我不知道,但这在 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.

我必须将 <button type="submit"> 替换为 <input type="submit"> 才能使 Dashlane 正常工作。不敢相信这甚至是一件事……
Z
ZeWaren

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

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

在 Chrome 34.0 上看到。


Chrome 46 修复了它的错误行为,在 ajax 请求之后隐藏表单就足够了。请参阅stackoverflow.com/a/33113374/810109
j
jpaugh

我建议查看 Firefox source code。它实际上是非常简单的代码。

您要查看的方法是 _onFormSubmit_getFormFields_getPasswordFields

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


h
hendrikbeck

除了已经说过的很多内容之外,我还意识到不能“禁用”输入字段。我们有一个多步骤登录,首先要求输入用户名,然后在下一个屏幕上输入密码。在第二个屏幕上,我们重复了电子邮件,但禁用了它,这阻止了 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">

我不会去推荐这个,但也许它指向某人在他们自己的代码中的某些东西:

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


对于需要提交其值但用户无法更改的输入的情况,您可能需要尝试“只读”而不是“禁用”。
k
keivan kashani

例如,如果您在输入 type=password 之前的表单中有两个 type=text,则浏览器会为您的用户名检测最近的输入 type=text。

这没关系,另一个输入有 is=username 和 name=username

为了解决这个问题,您必须将您想要保存的用户名输入准确地放在输入密码之前

祝你好运 :-)


J
Jeba Moses

主要关键词在这里,

   <input type="password">

尝试用更多细节来解释您的答案,因为这对其他人会有所帮助。