首页 > 解决方案 > 影响自动填充解决方法的 Javascript 执行顺序

问题描述

这个问题是关于我在我们的网站试图弥补 Chrome 坚持在不应该执行自动填充时遇到的一个问题。

请注意:这个问题并不是专门关于自动填充问题的,这在几年的过程中都有很好的记录。例如,以下是一些涵盖该问题的有用页面:

多年来,我们使用了几种类似于上述文章中记录的解决方案,尤其是第一篇文章。

随着开发人员开发出变通方法,Chrome 团队会努力禁用这些变通方法。目前我不知道任何有效的解决方法。Chromium 团队显然认为任何带有密码字段的表单都是登录表单,它不想轻易允许编辑密码的能力,同时保留自动混淆功能。

无论如何,我重申我并没有特别关注自动填充问题,而是我遇到的一些问题。

我们已经在我们的一些编辑页面上成功地反驳了这个问题,但由于以下问题,这是这个问题的核心,所以没有一个完整的解决方案。

问题是因为有问题的字段是电子邮件地址(用户名)和密码,所以页面上还有其他 javascript,这相当复杂。该javascript的目的是帮助用户使用以下功能:

  1. 确保该条目符合某些基本验证。
  2. 确保我们的数据库中尚未使用电子邮件地址。
  3. 确保该条目不违反某些其他策略,例如使用名字、姓氏等作为密码。

我们的一项措施(部分是为了对抗浏览器自动填充)让电子邮件地址和密码字段隐藏起来,并且仅在用户单击带有“更改电子邮件地址”标签之类的按钮后才会显示。这对用户产生了一些有益的影响,我不会详细说明,但也阻止了 Chrome 的自动填充。

然而,最近,Chrome 甚至开始自动填充隐藏字段。因此,当单击按钮并显示字段时,电子邮件地址中会填充数据。但是,填充的数据是用户 ID 而不是电子邮件地址,因为我们允许使用用户 ID 或电子邮件地址进行日志记录,并且通过某些 Chrome 设置,用户 ID 被保存。

处理此“功能”的下一步是添加一行 jquery 以在单击按钮时清除该字段的内容,如果未单击按钮,则让更新例程忽略虚假的自动填充。

正在发生的实际问题是,Chrome 似乎正在将值重新插入 DOM。其他作品似乎表明,每次 DOM 更改时,Chrome 都会反常地不断尝试执行自动填充。

因此,这是我尚未解决的一系列明显事件:

  1. 用户访问他的个人资料页面。
  2. Chrome 会自动填充隐藏的用户名。
  3. 用户点击“更改电子邮件地址”
  4. jquery 使用 val('') 清除字段的内容。
  5. 电子邮件地址字段上有一个 onblur 验证,但不应触发该字段,因为该字段未模糊。事实上,光标甚至还没有放在字段中——用户必须这样做。我们知道验证发生的原因是因为我们立即收到有关无效电子邮件地址的错误消息,因为它是用户 ID 格式而不是电子邮件地址格式。

这里发生了两件“不可能”的事情。

  1. 正在进行验证,似乎无法触发它。
  2. 我们已经使用 jquery 清除了该字段。但是验证(不应该发生)仍然看到原始的自动填充和无效内容。

可以解释这一点的一个理论是,当显示该字段时,焦点在 javascript 有时间实际清除 DOM 之前迅速进入该字段,并且焦点在眼睛看到它进入之前就离开了该字段。字段,从而在 jquery 生效之前再次触发验证。

所以理论上可能是事件的顺序是获得焦点,失去焦点,触发 onblur 验证,清除字段。这将产生观察到的效果。

所以问题的具体内容如下:

  1. 是什么导致了焦点的获得和丢失?
  2. 为什么在清除字段之前会发生这种情况,当字段可见时会发生这种情况?

然而,进一步的理论可能是“javascript 处理事件的顺序不是它出现的顺序,而是其他一些预定的顺序”。我已经看到了一些关于此的信息,但我不知道如何控制它来解决问题。

以下是一些代码片段。您会注意到一些以前有效的自动填充阻止策略仍然存在:

onblur=ValidFirstField()

<input type="password" autocomplete="new-password" name="password1" id="password1" size="20" maxlength="$MAX_PASSWORD_LEN" onkeydown="clearMessage('pw_message'); displayMessage('pw_strength');" onkeyup="chkPass(this.value);" onblur="ValidFirstField(this, 'Password', $MIN_PASSWORD_LEN, $MAX_PASSWORD_LEN, ValidPasswordSafety, ['$companyname', '$fname', '$lname', '$email1', '$email2'], 'pw_message', ' not allowed; please choose another.', 1, 'password2' );" >

验证请注意:字段名+'必须在'之间的代码行是乱序触发的验证:

function ValidFirstField(field1, fieldname, minlen, maxlen, cfunc, aProhibited, msg_field, bad_msg, common_msg, mark_field)
{
    if (!field1.value.length)
    {
        return;
    }
    var login_prompt = document.getElementById('login-prompt');
    if (login_prompt)
    {
        login_prompt.style.display = STYLE_NONE;    /* clear in case set via ajax */
    }
    var msg = document.getElementById(msg_field);
    msg.innerHTML = '';
    var allowSubmit = true;
    if (field1.value.length < minlen || field1.value.length > maxlen)
    {
        msg.innerHTML = fieldname + ' must be between ' + minlen + ' and ' + maxlen + ' characters: ' + field1.value.length;
        allowSubmit = false;
        field1.focus();     // TODO temporarily suppress to prevent focus/onblur race in IE
    }
...

显示字段并清除内容的jquery

$('#show-email').click(function()
{
    chg_email_clicked = true;
    $('#chg-email-clicked').val(1);
    // alert('chg=' + chg_email_clicked);
    $(this).hide();
    // from https://stackoverflow.com/questions/15738259/disabling-chrome-autofill mike nelson
    var $chrome_fake = $('.chrome-fake');
    $chrome_fake.show();
    window.setTimeout(function ()
    {
        $chrome_fake.hide();
    },1);
    $('#email1').val('');
    // var testemail1   = document.getElementById('email1').value;
    // alert(testemail1);
    $('.hide-email').show();
});

标签: javascriptjquerygoogle-chromeautofill

解决方案


推荐阅读