首页 > 解决方案 > 为什么 Chrome 会认为我的表单是信用卡表单?

问题描述

最小复制示例(jsfiddle,您需要在浏览器中保存信用卡才能看到此问题):

<!DOCTYPE html>
<html>
<head>
    <title>Test</title>
</head>
<body>
    <form method="post" action="Test.html" autocomplete="off">
        <div>
            <label>Basisnummer</label>
            <input type="text" />
            <input type="text" />
            <br>

            <label>Markenname</label>
            <input type="text" />
        </div>
    </form>
</body>
</html>

Chrome 85.0.4183.121 和 Edge 85.0.564.63 都认为这是一张信用卡表格,并决定帮助我的用户输入他们的信用卡数据,这根本没有帮助(因为这不是信用卡表格)并且混淆了我的用户见鬼了:

截屏


我知道以下解决方法:


无论如何,我宁愿使用浏览器而不是反对它,因此我的问题是:

为什么会这样?(既然它同时出现在 Chrome 和“新”Edge 中,那一定是 Chromium 的问题,而且由于 Chromium 是开源的,我们应该能够看到这里发生了什么,对吧?)

额外问题:我如何(正式)告诉 Chromium 这不是信用卡表格?


笔记:

标签: htmlformsgoogle-chromeinputautofill

解决方案


这是因为 Chome 对德语信用卡表格的自动检测过于激进。特别是,您的表格包含

  • 三个或更多领域,
  • 其中一个被标记为 a ...nummer,并且
  • 另一个被标记为...name.

这是一个更简单的最小示例,它与当前的金丝雀版本的 Chrome (87.0.4278.0) 重现了相同的问题:

<!DOCTYPE html>
<html>
<head>
    <title>Test</title>
</head>
<body>
    <div>
        <label>Nummer</label>
        <input type="text" />
        <input type="text" />
        <br>

        <label>Name</label>
        <input type="text" />
    </div>
</body>
</html>

查看 Chromium 的源码,我们可以看到下面的正则表达式用于检测信用卡号字段(components/autofill/core/common/autofill_regex_constants.cc):

const char kCardNumberRe[] =
    "(add)?(?:card|cc|acct).?(?:number|#|no|num|field)"
    "|(?<!telefon|haus|person|fødsels)nummer"  // de-DE, sv-SE, no
    "|カード番号&quot;                              // ja-JP
    "|Номер.*карты"                            // ru
    "|信用卡号|信用卡号码&quot;                     // zh-CN
    "|信用卡卡號&quot;                              // zh-TW
    "|카드"                                    // ko-KR
    // es/pt/fr
    "|(numero|número|numéro)(?!.*(document|fono|phone|réservation))";

我们可以看到(几乎)每个标有“...nummer”(= 德语中的“数字”)的字段都被视为信用卡号字段!

找到信用卡号字段后,标记为“...name”的后续字段将被视为信用卡名称字段(credit_card_field.cc):

// Sometimes the cardholder field is just labeled "name". Unfortunately
// this is a dangerously generic word to search for, since it will often
// match a name (not cardholder name) field before or after credit card
// fields. So we search for "name" only when we've already parsed at
// least one other credit card field and haven't yet parsed the
// expiration date (which usually appears at the end).
if (fields > 0 && !credit_card_field->expiration_month_ &&
    ParseField(scanner, base::UTF8ToUTF16(kNameOnCardContextualRe),
               &credit_card_field->cardholder_,
               {log_manager, "kNameOnCardContextualRe"})) {
  continue;

不幸的是,没有“官方”的方式告诉 Chrome “这真的不是信用卡字段”。最常见的解决方法autocomplete="cc-csc",但这在语义上是完全倒退的(错误地将字段标记为某种类型的信用卡字段以防止信用卡字段自动检测)。

我已经为此提交了一个错误报告,希望它有所帮助:


推荐阅读