Chrome浏览器忽略自动完成=closures

我创build了一个使用tagbox下拉菜单的web应用程序,除了我的首选浏览器Chrome(版本21.0.1180.89)之外,这个工具在所有浏览器中都很好用。

尽pipeinput字段和表单字段具有autocomplete="off"属性,但Chrome坚持显示该字段的以前条目的下拉历史logging,这将删除标记框列表。

根据我的经验,Chrome只会自动完成第一个<input type="password">和前一个<input> 。 所以我补充说:

 <input style="display:none"> <input type="password" style="display:none"> 

<form>的顶部,案例已经解决。

Chrome似乎忽略了autocomplete="off"除非它在<form autocomplete="off">标签上。

最好的解决scheme:

 <input type="text" name="email"> <input type="password" name="password" autocomplete="new-password"> 

要么

 <input type="email" name="email"> <input type="password" name="password" autocomplete="new-password"> 

适用于:

  • 铬:49,50,51,52,53,54,55,56,57和58

  • Firefox:44,45,46,47,48,49和50

要获得可靠的解决方法,您可以将此代码添加到布局页面:

 <div style="display: none;"> <input type="text" id="PreventChromeAutocomplete" name="PreventChromeAutocomplete" autocomplete="address-level4" /> </div> 

只有在表单中至less有一个其他input元素与其他任何自动完成值一起使用时,Chrome才会尊重autocomplete = off。

这不适用于密码字段 – 这些在Chrome中的处理方式非常不同。 有关更多详细信息,请参见https://code.google.com/p/chromium/issues/detail?id=468153

更新:由Chromium团队2016年3月11日closures的“不会修复”错误。请参阅最初提交的错误报告中的最新评论,以获取完整说明。 TL; DR:使用语义自动完成属性,例如autocomplete =“new-street-address”来避免Chrome执行自动填充。

Chrome版本34现在忽略了autocomplete=off , 看到这个 。

很多关于这是好事还是坏事的讨论? 你的意见是什么?

目前的解决scheme是使用type="search" 。 Google不会将自动填充应用于使用某种searchtypes的input。

请参阅: https : //twitter.com/Paul_Kinlan/status/596613148985171968

更新04/04/2016:看起来这是固定的! 请参阅http://codereview.chromium.org/1473733008

现代方法

只需使您的inputreadonly ,并在焦点上,将其删除。 这是一个非常简单的方法,浏览器不会填充readonlyinput。 因此,这种方法被接受,将来不会被未来的浏览器更新覆盖。

 <input type="text" onfocus="this.removeAttribute('readonly');" readonly /> 

对input进行相应设置,使其看起来不像readonlyinput

 input[readonly] { cursor: text; background-color: #fff; } 

工作的例子

浏览器不关心autocomplete =closures自动或甚至填充凭据错误的文本字段?

我通过将密码字段设置为只读并将其激活,当用户点击该字段或使用Tab键到该字段来修复它。

修复浏览器自动填写:只读,并设置焦点上的可写 (在鼠标点击和标签通过字段)

  <input type="password" readonly onfocus="$(this).removeAttr('readonly');"/> 

更新:移动Safari在字段中设置光标,但不显示虚拟键盘。 新的修复工作像以前一样,但处理虚拟键盘:

 <input id="email" readonly type="email" onfocus="if (this.hasAttribute('readonly')) { this.removeAttribute('readonly'); // fix for mobile safari to show virtual keyboard this.blur(); this.focus(); }" /> 

现场演示https://jsfiddle.net/danielsuess/n0scguv6/

// UpdateEnd

顺便说一下,我的观察更多的信息

有时我会注意到Chrome和Safari上的这种奇怪的行为,当有相同forms的密码字段 我想,浏览器查找密码字段来插入您保存的凭据。 然后它自动填充用户名到最近的文本typesinput字段,出现在DOM 的密码字段之前 (只是由于观察猜测)。 由于浏览器是最后一个实例,您无法控制它, 有时甚至autocomplete = off也不会阻止将凭据填充到错误的字段中,而不是用户或昵称字段。

那么晚了一点,但似乎有一点误解,应该如何autocomplete应该和不应该工作。 根据HTML规范,用户代理(本例中为Chrome)可以覆盖autocomplete

https://www.w3.org/TR/html5/forms.html#autofilling-form-controls:-the-autocomplete-attribute

用户代理可以允许用户覆盖元素的自动填充字段名称,例如,将其从“关”改变为“开”,以允许值被记住并预先填充,而不pipe页面作者的反对,或者始终“closures”,永远不会记住值。 但是,用户代理不应允许用户将自动填充字段名称从“closures”更改为“打开”或其他值,因为如果始终记住所有值,则无论站点的偏好如何,都会对用户造成严重的安全隐患。

所以在Chrome的情况下,开发人员基本上说过:“我们会留给用户根据自己的喜好来决定是否需要autocomplete工作,如果你不需要autocomplete ,不要在浏览器中启用它”。

然而,这似乎是我自己喜欢的一点点过分热心,但它是这样的。 该规范还讨论了此举的潜在安全影响:

“off”关键字表示控制的input数据是特别敏感的(例如核武器的激活码)。 或者它是一个永远不会被重用的值(例如,用于银行login的一次性密钥),并且因此用户将不得不每次都明确地input数据,而不是依赖于UA来预先填充他的价值; 或者文档提供自己的自动完成机制,并且不希望用户代理提供自动完成值。

所以在经历了与其他人一样的挫折之后,我find了适合我的解决scheme。 它与autocomplete="false"答案相似。

Mozilla的一篇文章谈到了这个问题:

https://developer.mozilla.org/en-US/docs/Web/Security/Securing_your_site/Turning_off_form_autocompletion

在某些情况下,即使autocomplete属性设置为off,浏览器也会一直提示自动填充值。 这种意外的行为对于开发者来说可能是相当困惑的 真正强制不完成的技巧是为该属性分配一个随机string

所以下面的代码应该工作:

 autocomplete="nope" 

以下各项应该如此:

 autocomplete="false" autocomplete="foo" autocomplete="bar" 

我看到的问题是,浏览器代理可能足够聪明,可以学习autocomplete属性,并在下次看到表单时应用它。 如果这样做的话,我可以看到仍然可以解决问题的唯一方法是在页面生成时dynamic更改autocomplete属性值。

有一点值得一提的是,许多浏览器将忽略login字段(用户名和密码)的autocomplete设置。 正如Mozilla文章所述:

为此,许多现代浏览器不支持login字段的自动完成=“closures”。

  • 如果网站为表单设置了autocomplete =“off”,并且表单中包含用户名和密码input字段,那么浏览器仍会提供记住此login信息,如果用户同意,则浏览器将在下次自动填充这些字段用户访问此页面。
  • 如果一个网站为用户名和密码input字段设置了autocomplete =“off”,那么浏览器仍然会提供记住这个login信息,如果用户同意,浏览器会在用户下一次访问这个页面时自动填充这些字段。

这是Firefox(从版本38开始),Google Chrome(从34开始)和Internet Explorer(从版本11开始)的行为。

最后关于该属性是属于form元素还是input元素。 规范再次有答案:

如果省略了autocomplete属性,则会使用与元素的表单所有者的自动完成属性的状态相对应的默认值(“on”或“off”)。 如果没有表单所有者,则使用值“on”。

所以。 把它放在表单上应该适用于所有的input字段。 把它放在一个单独的元素上应该只适用于那个元素(即使表单中没有一个)。 如果autocompletefunction没有设置,则默认为on

概要

在整个表单上禁用autocomplete

 <form autocomplete="off" ...> 

或者如果你dynamic需要这样做:

 <form autocomplete="random-string" ...> 

要禁用单个元素上的autocomplete (不pipe表单设置是否存在)

 <input autocomplete="off" ...> 

或者如果你dynamic需要这样做:

 <input autocomplete="random-string" ...> 

请记住,某些用户代理甚至可以覆盖您最难的尝试来禁用autocomplete

看到chrome忽略了autocomplete="off" ,我用一个愚蠢的方式解决了这个问题,那就是用“假input”来骗取chrome来填充它,而不是填充“真实”的。

例:

 <input type="text" name="username" style="display:none" value="fake input" /> <input type="text" name="username" value="real input"/> 

Chrome会填满“虚假input”,提交时,服务器将采取“真实input”的价值。

我张贴这个答案带来一个更新的解决scheme,以解决这个问题。 我目前使用的是Chrome 49,但没有给出答案。 我也正在寻找一个解决scheme,与其他浏览器和以前的版本。

将此代码放在表单的开头

 <div style="display: none;"> <input type="text" autocomplete="new-password"> <input type="password" autocomplete="new-password"> </div> 

然后,为你的真实密码字段,使用

 <input type="password" name="password" autocomplete="new-password"> 

如果此操作不再有效,或者如果您在其他浏览器或版本中遇到问题,请评论此答案。

批准时间:

  • Chrome:49
  • Firefox:44,45
  • 边缘:25
  • Internet Explorer:11

任何寻找解决scheme的人,我终于明白了。

如果页面是HTML5页面(我使用的是XHTML),Chrome浏览器只会遵循autocomplete =“off”。

我把我的页面转换为HTML5,问题就消失了(facepalm)。

直到上个星期,下面的两个解决scheme似乎适用于Chrome,IE和Firefox。 但随着Chrome版本48(仍然在49)的发布,他们不再工作:

  1. 下面的表格顶部:
 <input style="display:none" type="text" name="fakeUsername"/> <input style="display:none" type="password" name="fakePassword"/> 
  1. 以下在密码input元素中:

    自动填充=“closures”

所以为了快速解决这个问题,起初我尝试着使用最初设置密码input元素为禁用的主要方法,然后在文档就绪函数中使用setTimeout来重新启用它。

 setTimeout(function(){$('#PasswordData').prop('disabled', false);}, 50); 

但是,这似乎是如此疯狂,我做了一些更多的search,并发现禁用Chrome自动填充 @tibalts答案。 他的答案是在密码input中使用autocomplete =“new-password”,这似乎适用于所有的浏览器(我已经在这个阶段保留了我的固定编号1)。

以下是Google Chrome开发者讨论中的链接: https : //code.google.com/p/chromium/issues/detail?id = 370363#c7

你可以使用autocomplete="new-password"

 <input type="email" name="email"> <input type="password" name="password" autocomplete="new-password"> 

适用于:

  • Chrome:53,54,55
  • Firefox:48,49,50

而不是autocomplete =“off”使用autocomplete =“false” ;)

从: https : //stackoverflow.com/a/29582380/75799

从Chrome 42开始,这个线程中的解决scheme/攻击( 2015-05-21T12:50:23+00:00 )都不能用于禁用单个字段或整个表单的自动完成function。

编辑:我发现你实际上只需要在其他字段之前插入一个虚拟电子邮件字段到您的窗体(你可以隐藏它与display: none ),以防止自动完成。 我认为,铬存储某种forms的签名与每个自动完成的领域,并包括另一个电子邮件字段破坏这个签名,并防止自动完成。

 <form action="/login" method="post"> <input type="email" name="fake_email" style="display:none" aria-hidden="true"> <input type="email" name="email"> <input type="password" name="password"> <input type="submit"> </form> 

好消息是,由于“表单签名”被这样的破坏,没有一个字段是自动完成的,因此在提交之前不需要JS来清除伪造的字段。

老答案:

我发现唯一可行的方法是在真正的字段之前插入两个types为email和password的虚拟字段。 您可以将它们设置为display: none以隐藏它们(它不够聪明,无视这些字段):

 <form action="/login" method="post"> <input type="email" name="fake_email" style="display:none" aria-hidden="true"> <input type="password" name="fake_password" style="display:none" aria-hidden="true"> <input type="email" name="email"> <input type="password" name="password"> <input type="submit"> </form> 

不幸的是,这些字段必须在你的表单中(否则两组input都是自动填充的)。 所以,假的字段被真正的忽略,你需要一些JS运行在表单提交来清除它们:

 form.addEventListener('submit', function() { form.elements['fake_email'].value = ''; form.elements['fake_password'].value = ''; }); 

从上面注意到,用Javascript清除值可以覆盖自动完成。 所以,如果用JS禁用失去正确的行为是可以接受的,你可以简化所有这与一个JS自动完成“填充”为Chrome:

 (function(document) { function polyfillAutocomplete(nodes) { for(var i = 0, length = nodes.length; i < length; i++) { if(nodes[i].getAttribute('autocomplete') === 'off') { nodes[i].value = ''; } } } setTimeout(function() { polyfillAutocomplete(document.getElementsByTagName('input')); polyfillAutocomplete(document.getElementsByTagName('textarea')); }, 1); })(window.document); 

在v.34之后,在<form>标签处设置autocomplete="off"不起作用

我做了一些改变,以避免这种恼人的行为:

  1. 删除密码input的nameid
  2. 把一个类放在input中(例如: passwordInput

(到目前为止,Chrome浏览器不会把保存的密码放在input上,但是表单现在被破坏了)

最后,为了使表单工作,当用户点击提交button或者当你想要触发表单提交时,运行这个代码:

 var sI = $(".passwordInput")[0]; $(sI).attr("id", "password"); $(sI).attr("name", "password"); 

在我的情况下,我曾经在密码input中使用了hav id="password" name="password" ,所以在触发submition之前我把它们放回去了。

我刚刚更新到Chrome 49 , Diogo Cid的解决scheme不再工作。

我做了一个不同的解决方法隐藏和删除页面加载后运行时的字段。

Chrome现在忽略了将凭据应用到第一个显示的 type="password"字段和以前的type="text"字段的原始解决方法,所以我隐藏了两个使用CSS visibility: hidden;visibility: hidden;

 <!-- HTML --> <form> <!-- Fake fields --> <input class="chromeHack-autocomplete"> <input type="password" class="chromeHack-autocomplete"> <input type="text" placeholder="e-mail" autocomplete="off" /> <input type="password" placeholder="Password" autocomplete="off" /> </form> <!-- CSS --> .chromeHack-autocomplete { height: 0px !important; width: 0px !important; opacity: 0 !important; padding: 0 !important; margin: 0 !important; } <!--JavaScript (jQuery) --> jQuery(window).load(function() { $(".chromeHack-autocomplete").delay(100).hide(0, function() { $(this).remove(); }); }); 

我知道它可能看起来不是很优雅,但它的工作原理。

在Chrome 48+中使用这个解决scheme:

  1. 把虚假的领域放在真正的领域之前:

     <form autocomplete="off"> <input name="fake_email" class="visually-hidden" type="text"> <input name="fake_password" class="visually-hidden" type="password"> <input autocomplete="off" name="email" type="text"> <input autocomplete="off" name="password" type="password"> </form> 
  2. 隐藏假字段:

     .visually-hidden { margin: -1px; padding: 0; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); clip: rect(0, 0, 0, 0); position: absolute; } 
  3. 你做到了!

这也适用于旧版本。

虽然我同意自动完成应该是一个用户的select,但有些时候,Chrome是过度热心(其他浏览器也可能)。 例如,具有不同名称的密码字段仍会自动填充保存的密码,而前一个字段将填入用户名。 当表单是用于Web应用程序的用户pipe理表单时,这特别糟糕,而且您不希望自动填充使用您自己的凭据来填充它。

Chrome现在完全忽略了自动完成=“closures”。 虽然JS黑客可能工作,我find了一个简单的方法,在写作时:

将密码字段的值设置为控制字符8(PHP中的"\x08"或HTML中的&#8; "\x08" )。 这会停止Chrome自动填充字段,因为它有一个值,但没有input实际值,因为这是退格字符。

是的,这仍然是一个黑客,但它适用于我。 因人而异。

autocomplete=off在现代浏览器中被忽略 – 主要是由于密码pipe理器等。

你可以尝试添加这个autocomplete="new-password"它并不完全支持所有的浏览器,但它在一些工作

我发现这个解决scheme是最合适的:

 function clearChromeAutocomplete() { // not possible, let's try: if (navigator.userAgent.toLowerCase().indexOf('chrome') >= 0) { document.getElementById('adminForm').setAttribute('autocomplete', 'off'); setTimeout(function () { document.getElementById('adminForm').setAttribute('autocomplete', 'on'); }, 1500); } } 

必须在dom准备好之后或在表单呈现之后加载。

我以另一种方式解决。 你可以试试这个

 <input id="passfld" type="text" autocomplete="off" /> <script type="text/javascript"> // Using jQuery $(function(){ setTimeout(function(){ $("input#passfld").attr("type","password"); },10); }); // or in pure javascript window.onload=function(){ setTimeout(function(){ document.getElementById('passfld').type = 'password'; },10); } </script> 

隐藏的input元素技巧仍然可以工作(Chrome 43),以防止自动填充,但有一点要记住,Chrome将尝试基于占位符标记进行自动填充。 您需要将隐藏的input元素的占位符与您要禁用的input相匹配。

在我的情况下,我有一个占位符文本为“City或Zip”的字段,我正在使用Google Place自动填充function。 它似乎试图自动填充,就像它是地址表的一部分。 这个技巧只有在隐藏元素上放置了与真实input相同的占位符时才起作用:

 <input style="display:none;" type="text" placeholder="City or Zip" /> <input autocomplete="off" type="text" placeholder="City or Zip" /> 

我有一个类似的问题,其中input字段采取了名称或电子邮件。 我设置了自动完成=“closures”,但Chrome仍然强制提示。 原来是因为占位符文本里面有“name”和“email”这几个字。

例如

 <input type="text" placeholder="name or email" autocomplete="off" /> 

我通过在占位符中的文字中放置一个零宽度的空间来解决这个问题。 没有更多的Chrome自动完成。

 <input type="text" placeholder="nam&#8203;e or emai&#8203;l" autocomplete="off" /> 

尝试了所有的解决scheme后,下面是铬版的工作原理:45,带有密码字段的表格:

  jQuery('document').ready(function(){ //For disabling Chrome Autocomplete jQuery( ":text" ).attr('autocomplete','pre'+Math.random(0,100000000)); }); 

看起来这是固定的! 请参阅https://codereview.chromium.org/1473733008

这是我在Chrome版本51.0.2704.106上的工作。 <input id="user_name" type="text" name="user_name" autocomplete="off" required />并结合<input id="user_password" type="password" name="user_password" autocomplete="new-password" required /> 。 我的问题是,在实施new-password它仍然会显示user_name字段上的用户名下拉列表。

需要使用AutoComplete ='false',这将在Chrome浏览器上运行也使用代码

 <ng-form autocomplete="false"> ..... </ng-form> 

I've just tried the following, and it appears to do the trick on Chrome 53 – it also disables the "Use password for:" drop down when entering the password field.

Simply set your password input type to text , and then add the onfocus handler (inline or via jQuery/vanilla JS) to set the type to password :

 onfocus="this.setAttribute('type','password')" 

Or even better:

 onfocus="if(this.getAttribute('type')==='text') this.setAttribute('type','password')"