密码

时间:2016-01-27 22:42:07

标签: javascript html google-chrome

当您为某个网站保存了用户名和密码时,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中的重新加载按钮,则密码字段的值将为空字符串。

21 个答案:

答案 0 :(得分:36)

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

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

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

答案 1 :(得分:23)

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

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

编辑2016年8月10日

这仅适用于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正确报告密码值。解决方法是在提交时重新验证可能自动完成的所有输入(如果这是您要执行的操作)。

编辑2016年12月13日:

新的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)

截至12月16日的其他选项/ Chrome 54

我无法获取密码字段的值,但是,在短暂的时间内#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从不填充,无论互动如何。

在此方案中,没有提到的解决方法(例如触发blurinput事件)。我发现的唯一解决方法是在ajax进程重新呈现表单后重置密码字段值,例如:

$('input[type="password"]').val("");

完成上述操作后,Chrome实际上会再次自动填充密码,但实际填充了value

在我目前的用例中,我使用了ASP.NET的Ajax.BeginForm,并在AjaxOptions.OnSuccess回调中使用了上述解决方法。

答案 9 :(得分:1)

使用Angular时,Chrome中的新行为(仅允许在用户与页面交互后读取自动填充值)在某些情况下使用Angular的验证功能时会显示为一个问题(例如,使用标准方法)表单上的/ action属性)。由于提交处理程序立即执行,因此不允许表单验证程序从Chrome中捕获自动填充的值。

我找到的解决方案是在提交处理程序中显式调用表单控制器$commitViewValue函数,以在检查form.$validform.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>

因此,在某些情况下,它会在密码字段中闪烁一秒钟,* 不理想但 :/ ...