当您为某个网站保存了用户名和密码时,Chrome会自动填充该用户名和密码,但如果您尝试获取密码输入字段的值,则为空字符串即使有值,但是
如果您点击页面上的某处,则无法填写input type="password"
的值。
这是html结构和console.log
命令的小提琴user/pass。它在这里看不到,但它可以在每个具有登录表单的页面上重现,并且用户名和密码在页面加载时自动填充。如果在点击站点上的任何其他位置之前检查字段的值,它将为空String。
在Firefox或Internet Explorer中,情况并非如此,它会使用密码填充input
元素的值。
我使用的是Windows 7旗舰版64位操作系统,谷歌Chrome版本为48.0.2564.97 m
这是正常的行为,bug还是?
更新
如果单击F5重新加载页面并检查密码字段,则密码值将在那里。如果您点击左上角Chrome中的重新加载按钮,则密码字段的值将为空字符串。
答案 0 :(得分:36)
这似乎是Chrome中的一个错误。当Chrome在初始页面加载时自动填写密码(但不是刷新)时,该值会显示在屏幕上的表单字段中,但在Javascript中查询passwordField.value
会返回一个空字符串。如果您依赖于在Javascript中查看该值,则会阻止您这样做。一旦用户在页面上执行任何其他操作,例如单击页面上的任何位置,该值就会突然变为Javascript。
我实际上并不是100%确定这是否是一个错误,或者是否存在安全原因,例如通过欺骗浏览器填写密码来阻止隐藏框架窃取您的密码。
我们使用的解决方法是检测Chrome对其自动填充的字段所做的背景颜色更改。 Chrome会将自动填充字段的背景颜色设置为黄色,即使值不是这样,此更改也始终对Javascript可见。在Javascript中检测到这一点让我们知道该字段是自动填充了一个值,即使我们在Javascript中看到该值为空白。在我们的例子中,我们有一个登录表单,其中在您填写密码字段中的内容之前未启用提交按钮,并且检测到值或自动填充背景颜色足以确定某些内容在字段中。然后我们可以启用提交按钮,然后单击按钮(或按Enter键)立即使密码字段值对Javascript可见,因为与页面交互可以解决问题,因此我们可以从那里正常进行。
答案 1 :(得分:23)
Adam correctly stated这是一个错误(或预期的行为)。但是,之前的答案都没有说明如何解决这个问题,因此这里有一种强制Chrome将自动完成值视为实际值的方法。
有些事情需要按顺序发生,而且这只需要在Chrome而不是Firefox中运行,因此if
。
首先我们关注元素。然后,我们创建一个新的TextEvent
,并运行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();
这仅适用于Windows和Android上的Chrome。不适用于OSX。此外,它将在2016年9月停止工作,根据:
https://www.chromestatus.com/features/5718803933560832
另外,我已经开了一张Chromium票。
https://bugs.chromium.org/p/chromium/issues/detail?id=636425
截至8月12日,Chrome团队的一名成员在上述票据中表示,该行为不会发生变化,因为他们认为这不是一个错误。
也就是说,当前的行为已经从最初实施时开始调整。用户不再需要与要报告的值的密码输入进行交互。用户现在只需要与页面的任何部分进行交互(发送鼠标或键盘事件)。这意味着虽然在页面加载上运行验证仍然无效,但单击提交按钮将导致Chrome正确报告密码值。解决方法是在提交时重新验证可能自动完成的所有输入(如果这是您要执行的操作)。
新的Chromium门票已经打开并且收到的更好。如果有兴趣改变Chrome的这种行为,请为这张新票加注星标:
https://bugs.chromium.org/p/chromium/issues/detail?id=669724
答案 2 :(得分:8)
继续Andy Mercer said,这是我的工作。像很多人一样,我不需要实际的密码值。我真的只需要知道密码框已经自动填充,以便我可以显示正确的验证消息。
就个人而言,我不会使用建议的解决方案来检测Chrome自动填充导致的背景颜色变化。这种做法似乎很脆弱。这取决于黄色永不改变。但这可以通过扩展来改变,并在另一个基于Blink的浏览器(即Opera)中有所不同。此外,谷歌不会在将来使用不同的颜色。无论风格如何,我的方法都有效。
首先,在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);
}
答案 3 :(得分:4)
以下是我对此问题的解决方案:
$(document).ready(function(){
if ( $("input:-webkit-autofill").length ){
$(".error").text("Chrome autofill detected. Please click anywhere.");
}
});
$(document).click(function(){
$(".error").text("");
});
基本上,点击会让输入对用户可见,所以我要求用户点击,当他们这样做时,我会隐藏信息。
不是最优雅的解决方案,但可能是最快的。
答案 4 :(得分:4)
我无法获取密码字段的值,但是,在短暂的时间内#34;我可以通过选择密码来获取密码的长度,这足以让我启用提交按钮。
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);
答案 5 :(得分:3)
我找到了一个解决这个问题的解决方案,至少可以用于我的目的。
我有一个登录表单,我只想在加载后立即输入,但我在Chrome中遇到密码空白问题。
以下似乎有效,允许初始输入密钥失败,并在Chrome唤醒后再次重试并提供密码值。
$(function(){
// bind form submit loginOnSubmit
$('#loginForm').submit(loginOnSubmit);
// submit form when enter pressed on username or password inputs
$('#username,#password').keydown(function(e) {
if (e.keyCode == 13) {
$('#loginForm').submit(e);
return false;
}
});
});
function loginOnSubmit(e, passwordRetry) {
// on submit check if password is blank, if so run this again in 100 milliseconds
// passwordRetry flag prevents an infinite loop
if(password.value == "" && passwordRetry != true)
{
setTimeout(function(){loginOnSubmit(e,true);},100);
return false;
}
// login logic here
}
答案 6 :(得分:3)
刚刚写了一个与此相关的角度指令。结束以下代码:
if (isset($_POST['action'])) {
switch ($_POST['action']) {
case 'version':
echo "3.1.1";
break;
case 'info':
$obj = new stdClass();
$obj->slug = '...';
$obj->plugin_name = '...';
$obj->new_version = "3.1.0";
$obj->requires = '4.7';
$obj->tested = '4.7.3';
$obj->downloaded = 12540;
$obj->last_updated = '2017-02-12';
$obj->homepage = '...';
$obj->sections = array(
'description' => '...'
);
$obj->download_link = 'https://.../latest.zip';
echo serialize($obj);
break;
case 'license':
echo 'false';
break;
}
} else {
header('Cache-Control: public');
header('Content-Description: File Transfer');
header('Content-Type: application/zip');
readfile('latest.zip');
}
ps:它不会100%检测到任何时间,镀铬可能需要超过5秒才能填充输入。
答案 7 :(得分:3)
Adam指定的解决方法:
...检测Chrome对其自动填充的字段所做的背景颜色更改。 Chrome会将自动填充字段的背景颜色设置为黄色,即使值不是这样,此更改也始终对Javascript可见。在Javascript中检测到这一点让我们知道该字段已自动填充了一个值,即使我们在Javascript中看到该值为空白
我确实喜欢这样: -
getComputedStyle(element).backgroundColor === "rgb(250, 255, 189)"
其中rgb(250,255,189)是黄色,Chrome适用于自动填充输入。
答案 8 :(得分:1)
Chrome的预期行为是,自动填充的密码在DOM中具有空value
,直到用户以某种方式与框架交互,此时chrome实际填充了该值。在此之前,任何客户端验证或尝试ajax提交表单都会将密码视为空。
这样可以在框架交互中填充密码值'行为不一致。我发现当表单托管在同一个iframe中时,它只能在第一次加载时运行,而不会在后续加载时运行。
这在首次加载时填充自动填充密码的ajax表单中最为明显,但是如果该密码无效且ajax提交重新呈现表单DOM,则自动完成的密码会在视觉上重新显示,但value
从不填充,无论互动如何。
在此方案中,没有提到的解决方法(例如触发blur
或input
事件)。我发现的唯一解决方法是在ajax进程重新呈现表单后重置密码字段值,例如:
$('input[type="password"]').val("");
完成上述操作后,Chrome实际上会再次自动填充密码,但实际填充了value
。
在我目前的用例中,我使用了ASP.NET的Ajax.BeginForm,并在AjaxOptions.OnSuccess回调中使用了上述解决方法。
答案 9 :(得分:1)
使用Angular时,Chrome中的新行为(仅允许在用户与页面交互后读取自动填充值)在某些情况下使用Angular的验证功能时会显示为一个问题(例如,使用标准方法)表单上的/ action属性)。由于提交处理程序立即执行,因此不允许表单验证程序从Chrome中捕获自动填充的值。
我找到的解决方案是在提交处理程序中显式调用表单控制器$commitViewValue
函数,以在检查form.$valid
或form.invalid
等之前触发重新验证。
示例:
function submit ($event) {
// Allow model to be updated by Chrome autofill
// @see http://stackoverflow.com/questions/35049555/chrome-autofill-autocomplete-no-value-for-password
$scope.loginModule.$commitViewValue();
if ($scope.loginModule.$invalid) {
// Disallow login
$scope.loginModule.$submitted = true;
$event.preventDefault();
} else {
// Allow login
}
}
虽然到目前为止这对我们有用,但如果有人为此问题找到了另一个更优雅的工作,我会非常感兴趣。
答案 10 :(得分:1)
$element.is("*:-webkit-autofill")
适合我
答案 11 :(得分:0)
var txtInput = $(sTxt);
txtInput.focus();
txtInput.select();
此解决方案适用于我的情况。 使用jQuery 3.1.1。
答案 12 :(得分:0)
这不是一个错误。这是一个安全问题。想象一下,如果没有用户可以使用javascript来检索自动填充的密码。确认。
答案 13 :(得分:0)
如果您希望将输入视为已完成,请尝试触发blur
:
$('input[type="password"]').blur();
答案 14 :(得分:0)
自动填充功能已成功停用。 有效!
<强> [HTML] 强>
<div id="login_screen" style="min-height: 45px;">
<input id="password_1" type="text" name="password">
</div>
<强> [JQuery的] 强>
$("#login_screen").on('keyup keydown mousedown', '#password_1', function (e) {
let elem = $(this);
if (elem.val().length > 0 && elem.attr("type") === "text") {
elem.attr("type", "password");
} else {
setTimeout(function () {
if (elem.val().length === 0) {
elem.attr("type", "text");
elem.hide();
setTimeout(function () {
elem.show().focus();
}, 1);
}
}, 1);
}
if (elem.val() === "" && e.type === "mousedown") {
elem.hide();
setTimeout(function () {
elem.show().focus();
}, 1);
}
});
答案 15 :(得分:0)
只需在用户名字段中将自动完成属性设置为用户名,在密码字段中将new-password设置为;
<input type="text" id="username" autocomplete="username">
<input type="password" id="password" autocomplete="new-password" >
答案 16 :(得分:0)
在我看来,这些解决方案似乎都不起作用。
我认为这值得一提,如果您想将其用于CSS样式,则可以使用-webkit-autofill属性,如下所示:
input:-webkit-autofill~.label,
input:-webkit-autofill:hover~.label,
input:-webkit-autofill:focus~.label
input:focus~.label,
input:not(.empty)~.label {
top: -12px;
font-size: 12px;
color: rgba(0, 0, 0, .4);
font-weight: 600
}
答案 17 :(得分:0)
您提到:
如果您在页面上的任何位置单击,无论输入type =“ password”的值将填充在哪里。
这就是为什么我只使用$('body').click();
模拟第一次单击,然后在JavaScript中提供该值的原因。
此外,我在注册表单密码字段中设置了autocomplete="new-password"
,以便该字段不会自动填写,用户必须填写新密码。
有关更多信息,请参见this Google Developers page。
答案 18 :(得分:0)
我的解决方案将CSS与chrome自动完成颜色进行比较...
$('input, select, textarea').each(function(){
var inputValue = $(this).val();
if ( inputValue != "" || $(this).css("background-color") != "rgba(255, 255, 255, 0)") {
$(this).parents('.form-group').addClass('focused');
}
});
答案 19 :(得分:0)
我尝试了所有解决方案,但对我没有用,所以我想到了这个。 我的问题是我有一个输入,当占位符被填充时,它会移动占位符的顶部,当然,当Chrome自动填充时,这是不起作用的。 仅在Chrome中测试过:
setTimeout(function () {
var autofilled = document.querySelectorAll('input:-webkit-autofill');
for (var i = 0; i < autofilled.length; i++) {
Do something with your input autofilled
}
}, 200);
答案 20 :(得分:0)
令人惊讶的是,到 2021 年,Chrome 还没有解决这个问题,自 2014 年以来,我遇到了自动完成问题,但仍然没有。
Chrome 功能自动完成对用户具有误导性,我不知道他们试图实现什么但看起来不太好。
就像现在一样,表单会向用户显示自动完成的文本(用户/电子邮件/密码),但在后台 html - 值不在元素内部。 由于值不在字段中,因此自定义验证将禁用提交按钮。
检查字段值的脚本会说 value 为 null,这对用户来说更加混乱,因为他/她可以看到文本在那里,并且可以假设它是有效的,从而导致混淆 delete-one 插入一个字符。 (尴尬的是,我不得不承认我不知道你需要点击 HTML 的正文,所以我想知道有多少用户不知道)
在我的情况下,我希望总是有空的字段,然后发现它只是不必要地花费时间让它工作。
如果我们尝试 autocomplete=off
,我们会发现它不起作用。为了验证字段并假设启用按钮,我们需要做一些技巧。
(请记住,我已经尝试过 autocomplete=password
new-password)和来自 official resource 的其他类型的 Hocus-Pocus 诡计。
最后我做到了。
<script>
$('#user').value = ' '; //one space
$('#pass').value = ' '; // one space - if this is empty/null it will autopopulate regardless of on load event
window.addEventListener('load', () => {
$('#user').value = ''; // empty string
$('#pass').value = ''; // empty string
});
</script>
因此,在某些情况下,它会在密码字段中闪烁一秒钟,*
不理想但 :/ ...