【发布时间】:2019-12-13 12:30:54
【问题描述】:
关于这个的帖子很少。您花费数小时检查每个答案、测试、阅读 cmets,以发现没有解决方案。你在 2019 年做了什么,Chrome 76 有效?
【问题讨论】:
标签: forms google-chrome autocomplete street-address
关于这个的帖子很少。您花费数小时检查每个答案、测试、阅读 cmets,以发现没有解决方案。你在 2019 年做了什么,Chrome 76 有效?
【问题讨论】:
标签: forms google-chrome autocomplete street-address
2020 年 1 月更新:似乎从 Chrome 79 开始,自动完成(定义见此处)不再将 autocomplete="some-unrecognised-value" 视为等于 autocomplete="on",所以现在 autocomplete="nope" 或类似有效禁用自动完成和自动填充。
2020 年 4 月更新:他们再次更改了它。从 Chrome 81 开始,autocomplete="some-unrecognised-value" 在禁用自动完成机制方面不再有效。然而,自动填充现在似乎比以前保守得多——它仍然不符合规范(带有name="email" 和autocomplete="off" 的字段仍会收到自动填充建议),但它不提供虚假地址随机表单字段上的片段。因此,我现在的建议是使用autocomplete="off"。如果您想在名为 email 的字段上执行此操作,那么您可能不走运:-(
TL,DR:autocomplete 属性似乎没有设置可以可靠地关闭所有自动完成下拉菜单。然而,导致这种情况的情况非常复杂,值得记录,希望能清除大量相互矛盾的建议......
当前 (76.0.3809.132) 版本的 Chrome 中存在两种不同的机制,我们将其称为 Autofill 和 Autocomplete(不一定是它们的正式名称):
自动填充功能会尝试使用您浏览器设置中存储的地址信息来填写表格。它可以通过下拉列表底部的“管理地址...”选项(或类似选项)来识别。此功能不尊重 autocomplete="off" 或 autocomplete="false",这是 Chrome 开发人员的深思熟虑的决定。
在a statement outlining this decision,zkoch 提供了这个解决方法:
如果您真的想禁用自动填充,我们的建议是 这一点是利用autocomplete属性给出valid, 您的领域的语义含义。如果我们遇到自动完成 我们无法识别的属性,我们不会尝试填充它。
例如,如果您的 CRM 工具中有地址输入字段 你不想让 Chrome 自动填充,你可以给它语义 这意味着相对于您的要求是有意义的:例如 自动完成=“新用户街道地址”。如果 Chrome 遇到这种情况,它 不会尝试自动填充该字段。
这是尝试解决方案的基础,例如autocomplete="nope";自动填充机制将跳过它无法识别的具有autocomplete 属性值的任何字段。
实现此决定的代码,记录在案:https://chromium.googlesource.com/chromium/src/+/refs/tags/78.0.3903.1/components/autofill/core/browser/form_structure.cc#1218
自动完成功能提供了该表单字段中先前提交的值的下拉列表。此下拉列表没有“管理地址...”选项。自动完成确实支持autocomplete="off" 或autocomplete="false" 属性;任何其他值(包括“无效”值,例如 autocomplete="nope")都会使其保持启用状态。
无法通过autocomplete 下拉菜单关闭自动完成下拉菜单;任何禁用自动填充的值都将启用自动完成,反之亦然。任何认为自己找到了可行的解决方案(通过autocomplete 或其他方法,例如 CSS hacks)的人都应该检查它是否适用于两种机制。
不幸的是,要让 Chrome 的开发人员相信这已被破坏,可能会是一场艰苦的斗争。 Autofill 的开发人员显然认为他们做出了一个经过深思熟虑的决定,即打破autocomplete="off",同时为 Web 开发人员提供替代方案;由于比他们意识到的更微妙的原因,这种选择被打破了。从他们的角度来看,由此产生的howls of protest 来自心怀不满的开发人员,他们懒得跳过一个小圈子并更新他们的autocomplete="off" 属性。在所有的噪音中,信息没有通过:箍坏了。
【讨论】:
尝试在您的输入字段中使用type="search" 而不是“文本”,我已经这样做了几次,它对我有用。
【讨论】:
截至 2019 年 12 月 6 日,Chrome v78.x
autocomplete="off" 等标准方法现在几乎可以用于最新版本的 Chrome。除了这个:
这东西真的很糟糕,因为它不仅不尊重"nope" 之类的标准/非标准值,而且实际上没有办法关闭它,除非输入甚至与 "addressy 没有远程关系" 条款。
如果不使用与地址相关的词,我们究竟如何才能显示与地址相关的输入字段? 这是有史以来最简单的解决方案。
确保输入元素的 name 和 id 不包含任何与地址相关的字词。 id="input-street" 或 name="destination-zip" 之类的属性是大忌。
这是最关键的部分:如果您需要对文本输入或其任何相邻元素使用任何人类可读的地址术语,请插入“不可见”零宽度joiner (‌) 在所述术语的字母之间。通过这种方式,我们可以欺骗 Chrome 的 AI 能力并绕过其严格的自动补全行为。
一些工作示例:
<input id="input-stret" placeholder="S‌treet" autocomplete="off">
<form action="/action_page.php">
<label for="product-addres">Product A‌ddress</label>
<input name="addres" id="product-addres" autocomplete="off">
</form>
然后就可以了。不再有用于管理地址的烦人菜单,也没有任何常规的自动完成菜单。
【讨论】:
<input> 中没有name 或id 属性的空字符对我来说很好用(在<label> 中的每个单词中)。困难的部分来自 Angular (8) 中的双向绑定。我们必须将这个:<label>{{ foo }}</label> 移动到这个:<label [innerHTML]="foo"></label> 并将 foo 中的空字符更改为 &#8205;:public const foo: string = 'Fi&#8205;rst Na&#8205;me'; 因为空字符(上面提到的)在 HTML 中呈现时显示为未知字符.我还为每个<input> 和<form> 使用了autocomplete="off"。
正如gasman's answer 解释的那样,autofill 和 autocomplete 功能都必须禁用,这在单个输入上似乎是不可能的。
我发现的唯一可行的解决方案是在输入上设置autocomplete="off",并在傻瓜autofill 的真实输入之前添加隐藏的假输入,如下所示:
<input name="Fake_Username" id="Fake_Username" type="text" style="display:none">
<input name="Fake_Password" id="Fake_Password" type="password" style="display:none">
<input name="NameInput" id="NameInput" type="text" autocomplete="off">
【讨论】:
* 此答案不正确。我已经发布了一个更好(但更丑)的解决方案作为新答案并保留了这个答案,因为某些部分可能仍然有用。如果这不是在stackoverflow上处理错误答案的方法,请随意删除这个*
考虑使用 autocomplete=
例如,如果一个字段是在时间戳 TS 请求页面后创建的第 N 个字段,则其
对自动完成的影响:由于
对自动填充的影响:chromium 通过将其指纹与之前遇到的字段的指纹进行比较来识别字段(请参阅form_field_data.cc)。如果被识别,它可能会提供一个记住值的列表。指纹包含自动完成属性的值。由于没有两个 nonce 相等,因此不会识别任何字段。
注意事项:
与 gasman 的回复相比,此处使用的术语 autocomplete 和 autofill 互换了。
所有字段都应在客户端动态创建(除非您愿意不缓存页面)。
【讨论】:
autocomplete="nope_20191017_123" 仍然给出记住的建议来自以前的提交(使用不同的自动完成值)。我可以看到 form_field_data.cc 确实是基于autocomplete_attribute 区分字段 - 也许它已经被规范化为真/假?
禁用自动填充: 将自动完成属性设置为非标准值,例如“不”。
禁用自动完成: 提交表单时,自动完成功能会存储字段名称及其值。 除了将自动完成设置为“off”/“false”(请参阅why)之外,没有(几乎,参见注释 1)可以采取任何措施来防止存储。 不幸的是,这不是一个选项,因为它会启用自动填充。
但是,可以通过将“!
在客户端,这可以通过以下 javascript 行(在页面加载时)来实现:
Array.prototype.slice.call(document.body.getElementsByTagName('INPUT'))
.forEach(function(elt) { elt.name += '!' + new Date().getTime(); });
在服务器端,以“!”开头的部分(如果有)应该从变量名中删除(在接收到 post 变量时)。
PS:这个答案是对我早期解决方案的勘误表,它更清洁但没有经过充分测试,并且 - 正如 gasman 正确指出的 - 不适用于普通形式。这个新的解决方案在 Chrome Canary 79 上进行了测试,确实有效,影响相对较小并且降级很好。尽管如此,我对发布这个黑客感到内疚,如果我以真实的形式遇到它,我会更加内疚。它*非常*脏。
注意 1: 阻止存储的唯一方法是首先不设置 name 属性(或取消设置),这需要拦截提交事件以发布数据“手动”(使用 XMLHttpRequest)。由于问题是关于形式的,而且这种策略绕过了传统的形式机制,我没有详细说明这种方法。不过,这是一个更好的解决方案。
附录:我决定跟进注释 1,因为我真的不喜欢非本地化的解决方案。这是 vanilla JS 中的本地化版本,它将所有影响限制在客户端的单个位置。将其作为脚本附加到文档正文或将其放入文档的 onload 处理程序中。
function disableInputSuggestions(form) { // note: code uses ECMA5 features
// tweak the inputs of form
var inputs = Array.prototype.slice.call(form.getElementsByTagName('INPUT'));
var nonce = Date.now();
inputs.forEach(function(input, i) {
input.autocomplete = 'nope'; // prevent autocomplete
input.originalName = input.name || input.id; // to not let this code break form handling of inputs without names (browsers fallback to the id in that case)
input.name = nonce + '_' + i; // prevent autofill (if you're willing to eliminate all input ids first, then clear the name instead)
});
// replace the default submit handler by a custom one
form.onsubmit = function(ev) {
// get the form data using the original variable names
var formData = new FormData();
inputs.forEach(function(input) { formData.set(input.originalName, input.value); });
// submit the form data using XMLHttpRequest (alternatively, use a helper form or temporarily undo the tweaks to form)
var submitter = new XMLHttpRequest();
submitter.open(form.getAttribute('method'), form.getAttribute('action'));
submitter.onreadystatechange = function() {
if(submitter.readyState == 4 && submitter.status == 200) {
// handle the server response, here assuming the default form.target = "_self"
document.open();
document.write(submitter.responseText);
document.close();
}
}
submitter.send(formData);
return false; // prevent submitting form
};
}
disableInputSuggestions(document.forms.myForm); // assumed: the form has id = myForm
【讨论】:
在 Chrome 91 中
您需要使用一个随机值,这意味着每次加载页面时都会更改的值。
从我所做的测试来看,chrome 似乎记住了它已经遇到的任何属性值,并且会在下一次建议该属性值的最后一次看到的值。因此,如果您输入 autocomplete="nope",chrome 会记住 autocomplete="nope" 等于您输入 autocomplete="nope" 的最后一个值。
通过使用 chrome 从未见过的唯一随机值,它不会提出任何建议,因为它从未见过该值。
PHP 7 示例
<input type="text" name="firstname" autocomplete="<?= bin2hex(random_bytes(10)) ?>" />
限制
它似乎对地址字段有效,但对登录字段没有影响。我没有使用信用卡字段进行测试。
【讨论】:
Chrome 版本 81。
对我来说,当输入类型为 TEL、EMAIL 或 SEARCH 时,它适用于 autocomplete='disabled'。 当输入类型为 NUMBER 时,它适用于 autocomplete='off'。
但是当输入类型是 TEXT .. 它可能与 autocomplete='off' 一起使用。如果没有,它将使用 autocomplete='disabled'。
你可以试试这个,也许它对你有用(它适用于我 95% 的情况):
// Désactivation de l'autocomplete des input text
function setAutocomplete(val) {
var E = document.getElementsByTagName('INPUT');
for (var i = 0 ; i < E.length ; i++) {
if (E[i].name == 'txt_nom') { console.log('txt_nom', E[i]); }
var type = E[i].type.toUpperCase();
if (E[i].autocomplete != '') { continue; }
if (type == 'HIDDEN') {
//
} else if (type == 'NUMBER') {
E[i].autocomplete = 'off';
} else if ((type == 'TEL') || (type == 'EMAIL') || (type == 'SEARCH')) {
E[i].autocomplete = 'disabled';
} else {
E[i].autocomplete = val;
}
}
}
// Exécution de diverses fonctions à la fin de chaque chargement
window.addEventListener("load", function() {
// Désactivation de l'autocomplete des input text
setAutocomplete('off');
});
【讨论】:
试试这个,我用了这个小技巧,它一直有效到现在(2020 年 9 月)。我希望这对很多人有用
--HTML--
<input type="text" name="example" autocomplete="off">
--Javascript--
let elements = document.querySelectorAll('[autocomplete="off"]');
elements.forEach(element => {
element.setAttribute("readonly", "readonly");
element.style.backgroundColor = "inherit";
setTimeout(() => {
element.removeAttribute("readonly");
}, 500);
})
【讨论】:
我制作了一个小型 jQuery 插件,可以从任何浏览器禁用任何类型的自动完成功能
用于form标签,参数少,可与其他jQuery方法嵌套。
$('#login_form').randomizeFormFields();
它改变了这个:
<form id="login_form" action="" method="post">
<input type="text" name="email">
<input type="password" name="secret">
</form>
进入这个:
<form id="login_form" action="" method="post">
<input type="text" name="yQoiFZkCrzwWXN3WWgM8Jblby">
<input type="password" name="ono1qamA9CzrH4tW2COoRtFKI">
</form>
提交时保留原始名称
// returned post (php example)
array(2) {
["email"]=>
string(16) "email@domain.com"
["secret"]=>
string(19) "supersecretpassword"
}
https://github.com/cicerogeorge/randomize-form-fields
如果你有想法,请分叉
【讨论】:
我已尝试对 html 形式的 EmailId 文本框使用 autocomplete = "off" 和 autocomplete = "nope",但它不适用于 Google Chrome。所以我尝试了以下对我有用的更改。
<input type="email" class="tbx-input" name="Email" style="display:none;">
<input type="email" class="tbx-input" name="Email" id="Email" placeholder=" " required autocomplete="nope">
【讨论】:
autocomplete='nope'
这是目前适用于 Chrome 76 的解决方案。
【讨论】: