Chrome 自动填充/自动完成没有密码值

IT技术 javascript html google-chrome
2021-01-26 07:36:01

当您为某个站点保存了用户名和密码时,Chrome 会自动填充该用户名和密码,但如果您尝试获取密码输入字段的值,即使存在 ****** 值,它也是空字符串。

如果您单击页面上的某处,则无论在哪里input type="password"都会填充的值

这是html 结构和命令的Fiddle用户/传递console.log它在这里看不到,但可以在每个有登录表单的页面上复制,并且在页面加载时自动填充用户名和密码。如果您在单击站点上的任何其他位置之前检查该字段的值,它将是空字符串。

在 Firefox 或 Internet Explorer 中不是这种情况,它会input用密码填充元素的值

我使用的是 Windows 7 Ultimate 64 位操作系统,Google Chrome 版本为 48.0.2564.97 m

这是正常行为,错误还是?

更新:

如果您单击 F5 重新加载页面并检查密码字段,密码值将在那里。如果您单击 Chrome 左上角的重新加载按钮,密码字段的值将为空字符串。

6个回答

这似乎是 Chrome 中的一个错误。当 Chrome 在初始页面加载(但不是刷新)时自动填充密码时,该值会出现在屏幕上的表单字段中,但passwordField.value在 Javascript 中查询会返回一个空字符串。如果您依赖于在 Javascript 中看到该值,这将阻止您这样做。一旦用户在页面上执行任何其他操作,例如单击页面上的任意位置,该值就会突然对 Javascript 可见。

我实际上并不能 100% 确定这是否是一个错误,或者是否有这样做的安全原因,例如通过欺骗浏览器填写密码来防止隐藏框架窃取您的密码。

我们使用的一种解决方法是检测 Chrome 对其自动填充的字段所做的背景颜色更改。Chrome 将自动填充字段的背景着色为黄色,即使值不存在,Javascript 也始终可以看到此更改。在 Javascript 中检测到这一点让我们知道该字段已自动填充了一个值,即使我们在 Javascript 中将该值视为空白。在我们的例子中,我们有一个登录表单,其中提交按钮在您在密码字段中填写某些内容之前不会启用,并且检测值或自动填充背景颜色足以确定该字段中有某些内容. 然后我们可以启用提交按钮,单击按钮(或按 Enter 键)立即使密码字段值对 Javascript 可见,因为与页面交互可以解决问题,

嗨,亚当。我想出了一种方法来触发 Chrome 将值视为真实值,以便.value可以访问,并将其添加为答案。该错误尚未修复,但至少有一个解决方案。
2021-03-24 07:36:01
@AdamHamilton 你好,我遇到了这个问题,我认为我们可以模拟一个点击/按键事件来模拟“点击页面上的任何地方”,使该值对 javascript 可见。你试过这个吗?
2021-03-25 07:36:01
我不知道自动填充可以花费的最长时间,特别是如果用户有阻止渲染的浏览器扩展或中断页面加载的东西,它的字段使用脚本动态注入页面。当自动填充不知道要做什么时,用户也可能从自动填充中手动选择,例如从“其他密码”对话框中进行选择。我通过使用 setInterval 轮询该字段来处理此问题,以便我可以快速响应,但也可以随着时间的推移进行监控。
2021-03-30 07:36:01
我试过了,但我自己没有运气。我怀疑浏览器正试图专门阻止它,因为它可能试图通过将密码填充到您未与之交互的框架中来防止泄露密码。因此,如果我的理论是正确的,它会寻找实际的用户驱动交互。可能我只是没有尝试正确的方法,但我确实通过了这一点。
2021-03-30 07:36:01
自动填充所需的最长时间是多少?我注意到即使是 300 毫秒也不够时间......
2021-04-13 07:36:01

截至 2016 年 7 月 8 日的工作答复

亚当正确地指出这是一个错误(或预期的行为)。然而,之前的答案都没有真正说明如何解决这个问题,所以这里有一种方法可以强制 Chrome 将自动完成的值视为真实值。

有几件事需要按顺序发生,这需要只在 Chrome 而不是 Firefox 中运行,因此if.

首先我们关注元素。然后我们创建一个 newTextEvent和 run initTextEvent,它将我们指定的自定义字符串(我使用“@@@@@”)添加到值的开头。这会触发 Chrome 实际上开始表现得好像值是真实的。然后我们可以删除我们添加的自定义字符串,然后我们取消焦点。


代码:

input.focus();

var event = document.createEvent('TextEvent');

if ( event.initTextEvent ) {

    event.initTextEvent('textInput', true, true, window, '@@@@@');

    input.dispatchEvent(event);

    input.value = input.value.replace('@@@@@','');

}

input.blur();

编辑 2016 年 8 月 10 日

这仅适用于 Windows 和 Android 上的 Chrome。不适用于 OSX。此外,根据以下信息,它将在 2016 年 9 月完全停止工作:

https://www.chromestatus.com/features/57188​​03933560832

另外,我开了一张 Chromium 票。

https://bugs.chromium.org/p/chromium/issues/detail?id=636425

截至 8 月 12 日,Chrome 团队的一名成员在上述工单上表示,行为不会改变,因为他们不认为这是一个错误。

长期解决建议:

也就是说,从第一次实施时起,当前的行为就已经进行了调整。用户不再需要与要报告的值的密码输入进行交互。用户现在只需要与页面的任何部分进行交互(发送鼠标或键盘事件)。这意味着虽然在页面加载上运行验证仍然不起作用,但单击提交按钮将导致 Chrome 正确报告密码值。解决方法是在提交时重新验证所有可能会自动完成的输入(如果这是您尝试执行的操作)。


2016 年 12 月 13 日编辑:

一张新的 Chromium 票已经打开,并且收到的效果更好。如果有兴趣改变 Chrome 的这种行为,请在这张新票上加注星标:

https://bugs.chromium.org/p/chromium/issues/detail?id=669724

继续Andy Mercer 所说的,这是我的工作。像很多人一样,我不需要实际的密码值。我真的只需要知道密码框已自动填充,以便我可以显示正确的验证消息。

就个人而言,我不会使用建议的解决方案来检测由 Chrome 自动填充引起的背景颜色变化。这种方法似乎很脆弱。这取决于永远不会改变的黄色。但这可以通过扩展程序进行更改,并且在另一个基于 Blink 的浏览器(即 Opera)中会有所不同。另外,不能保证 Google 将来不会使用不同的颜色。无论风格如何,我的方法都有效。

首先,在 CSS 中,我设置了应用伪类INPUT的内容-webkit-autofil

input:-webkit-autofill {
  content: "\feff"
}

然后,我创建了一个例程来检查要设置的内容:

const autofillContent = `"${String.fromCharCode(0xFEFF)}"`;
function checkAutofill(input) {
    if (!input.value) {
        const style = window.getComputedStyle(input);
        if (style.content !== autofillContent)
            return false;
    }

    //the autofill was detected
    input.classList.add('valid'); //replace this. do want you want to the input
    return true;
}

最后,我轮询input以允许自动填充时间完成:

const input = document.querySelector("input[type=password]");

if (!checkAutofill(input)) {
    let interval = 0;
    const intervalId = setInterval(() => {
        if (checkAutofill(input) || interval++ >= 20)
            clearInterval(intervalId);
    }, 100);
}
我使用了类似的间隔方法,因为我发现单个超时并不总是被触发,而且我不想在没有必要的情况下等待 2 秒。但是,我没有设置内容,而是使用document.querySelectorAll('input[type=\"password\"]:-webkit-autofill'). 我每 100 毫秒检查一次,如果找到或已过去 2 秒,我将取消间隔。似乎是我尝试过的最强大的解决方案。
2021-04-07 07:36:01

这是我对这个问题的解决方案:

$(document).ready(function(){
  if ( $("input:-webkit-autofill").length ){
    $(".error").text("Chrome autofill detected. Please click anywhere.");
  }
});

$(document).click(function(){
  $(".error").text("");
});

基本上,点击使输入对用户可见,所以我要求用户点击,当他们点击时,我隐藏消息。

不是最优雅的解决方案,但可能是最快的。

$(document).ready   

不等待浏览器的自动填充,它应该被替换为

$(window).on("load", checkforAutoFill())

12 月 16 日/Chrome 54 的另一种选择

我无法获取密码字段的值,但是,在“一小会儿”之后,我可以通过选择它来获取密码的长度,这足以让我启用提交按钮。

setTimeout(function() {
  // get the password field
  var pwd = document.getElementById('pwd');
  pwd.focus();
  pwd.select();
  var noChars = pwd.selectionEnd;
  // move focus to username field for first-time visitors
  document.getElementById('username').focus()
  if (noChars > 0) {
    document.getElementById('loginBtn').disabled = false;
  }
}, 100);
实际上,由于时间问题,这似乎只是偶尔起作用。有时noChars报告的值为 0,有时为正值。我不得不将超时增加到 200 毫秒,以使其或多或少地始终如一地工作。
2021-04-02 07:36:01