可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
You might already know, that Safari has a nasty autofill bug where it fills email, username and password fields no matter if you set autocomplete="off"
or not.
Here's a basic form:
<form action="/" method="post">
<p>
<label>E-mail</label>
<input type="text" name="email" value="" />
</p>
<p>
<label>Password</label>
<input type="password" name="password" value="" />
</p>
</form>
...Safari autofills those fields on page load like it should, job well done!
If you put autocomplete="off"
to the fields and/or the form element, Safari still autofills those fields:
<form action="/" method="post" autocomplete="off">
<p>
<label>E-mail</label>
<input type="text" name="email" value="" autocomplete="off" />
</p>
<p>
<label>Password</label>
<input type="password" name="password" value="" autocomplete="off" />
</p>
</form>
Even this doesn't work:
<form action="/" method="post" autocomplete="off">
<p>
<label>E-mail</label>
<input type="text" name="secretfield1" value="" autocomplete="off"/>
</p>
<p>
<label>Password</label>
<input type="password" name="secretfield2" value="" autocomplete="off" />
</p>
</form>
...since Safari looks up those <label>
elements if they contain words "E-mail", "Password" etc. and goes ahead with the autofill.
Aaaahhhhha!, I thought, and tried this:
<form action="/" method="post" autocomplete="off">
<p>
<label>%REPLACE_EMAIL_TITLE%</label>
<input type="text" name="%REPLACE_EMAIL_NAME%" value="" autocomplete="off"/>
</p>
<p>
<label>%REPLACE_PASSWORD_TITLE%</label>
<input type="password" name="%REPLACE_PASSWORD_NAME%" value="" autocomplete="off" />
</p>
</form>
...and replace %TAGS% with the real names using JavaScript. Safari autofill kicks in. No matter if you set a 10 second timeout on the replacement.
So, is this really the only option?
<form action="/" method="post" autocomplete="off">
<p>
<label>That electronic postal address we all use, but can't write the title here because Safari fills this with YOUR information if you have autofill turned on</label>
<input type="text" name="someelectronicpostaladdress" value="" autocomplete="off"/>
</p>
<p>
<label>A set of characters, letters, numbers and special characters that is so secret that only you or the user you are changing it for knows, but can't write the title here because Safari sucks</label>
<input type="password" name="setofseeecretcharacters" value="" autocomplete="off" />
</p>
</form>
I hope not?
UPDATE: @skithund pointed out in Twitter, that Safari is getting a 4.0.3 update, which mentions "Login AutoFill". Does anyone know if that update is going to fix this?
回答1:
I had the same problem. And though my solution is not perfect, it seems to work. Basically, Safari seems to look for an input field with password and username and always tries to fill it. So, my solution was to add a fake username and password field before the current one which Safari could fill. I tried using style="display: none;"
but that did not work. So, eventually, I just used style="position:absolute; top:-50px;"
and this hid the input field out of sight and seemed to work fine. I did not want to use JavaScript but I guess you could hide it with JavaScript.
Now Safari never autocompleted my username and password fields.
回答2:
The reason browsers are ignoring autocomplete=off
is because there have been some web-sites that tried to disable auto-completing of passwords.
That is wrong.
And in July 2014 Firefox was the last major browser to finally implement the change to ignore any web-site that tries to turn off autocompleting of passwords.
- June 2009: IEInternals blog where they discuss keeping the user in control (archive)
- February 2014: Chrome's announcement when they began ignoring
autocomplete=off
(archive)
- January 2014: Bugzilla Bug 956906 - ignore autocomplete="off" when offering to save passwords via the password manager (archive)
- Reddit discussion (archive)
One of the top user-complaints about our HTML Forms AutoComplete feature is “It doesn’t work– I don’t see any of my previously entered text.” When debugging such cases, we usually find that the site has explicitly disabled the feature using the provided attribute, but of course, users have no idea that the site has done so and simply assume that IE is buggy. In my experience, when features are hidden or replaced, users will usually blame the browser, not the website.
Any attempt by any web-site to circumvent the browser's preference is wrong, that is why browsers ignore it. There is no reason known why a web-site should try to disable saving of passwords.
- Chrome ignores it
- Safari ignores it
- IE ignores it
- Firefox ignores it
At this point, web developers typically protest “But I wouldn’t do this everywhere– only in a few little bits where it makes sense!” Even if that’s true, unfortunately, this is yet another case where there’s really no way for the browser to tell the difference. Remember, popup windows were once a happy, useful part of the web browsing experience, until their abuse by advertisers made them the bane of users everywhere. Inevitably, all browsers began blocking popups, breaking even the “good” sites that used popups with good taste and discretion.
What if I'm a special snowflake?
There are people who bring up a good use-case:
I have a shared, public area, kiosk style computer. We don't want someone to (accidentally or intentionally) save their password so the next user could use it.
That does not violate the statement:
Any attempt by any web-site to circumvent the browser's preference is wrong
That is because in the case of a shared kiosk:
- it is not the web-server that has the oddball policy
- it is the client user-agent that has the oddball policy
The browser (the shared computer) is the one that has the requirement that it not try to save passwords.
The correct way to prevent the browser from saving passwords
is to configure the browser to not save passwords.
Since you have locked down and control this kiosk computer: you control the settings. That includes the option of saving passwords.
In Chrome and Internet Explorer, you configure those options using Group Policies (e.g. registry keys).
From the Chrome Policy List:
AutoFillEnabled
Enable AutoFill
Data type: Boolean (REG_DWORD)
Windows registry location: Software\Policies\Chromium\AutoFillEnabled
Description: Enables Chromium's AutoFill feature and allows users to auto complete web forms using previously stored information such as address or credit card information. If you disable this setting, AutoFill will be inaccessible to users. If you enable this setting or do not set a value, AutoFill will remain under the control of the user. This will allow them to configure AutoFill profiles and to switch AutoFill on or off at their own discretion.
Please pass the word up to corporate managers that trying to disable autocompleting of password is wrong. It is so wrong that browsers are intentionally ignoring anyone who tries to do it. Those people should stop doing the wrong thing.™
回答3:
Fix: browser autofill in by readonly-mode and set writable on focus
<input type="password" readonly onfocus="this.removeAttribute('readonly');"/>
(focus = at mouse click and tabbing through fields)
Update:
Mobile Safari sets cursor in the field, but does not show virtual keyboard. New Fix works like before but handles virtual keyboard:
<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(); }" />
Live Demo https://jsfiddle.net/danielsuess/n0scguv6/
// UpdateEnd
Explanation: Browser auto fills credentials to wrong text field?
Ok, you just noticed that:
Safari autofill kicks in. No matter [what the fields are named] @Jari
and there's an assumption that:
Safari seems to look for an input field with password and username and always tries to fill it @user3172174
Sometimes I notice this strange behavior on Chrome and Safari, when there are password fields in the same form. I guess, the browser looks for a password field to insert your saved credentials. Then it autofills username into the nearest textlike-input field , that appears prior the password field in DOM (just guessing due to observation). As the browser is the last instance and you can not control it,
sometimes even autocomplete=off would not prevent to fill in credentials into wrong fields, but not user or nickname field.
This readonly-fix above worked for me.
回答4:
::-webkit-contacts-auto-fill-button, ::-webkit-credentials-auto-fill-button {
visibility: hidden;
pointer-events: none;
position: absolute;
right: 0;
}
回答5:
After scanning through Apple's Safari HTML pages and not finding anything on auto complete, I did some searching and thinking.
After reading a (mildly) related question on Apple discussions, I remembered that the default is to not allow remembered passwords, etc (which can be enabled in iDevice system settings, or at the prompt). Since Apple has moved this feature out of the browser and into their (proprietary, i)OS (screen shots on this article), I believe they are ignoring the HTML form/field property entirely.
Unless they change their mentality as to this feature, as I'm sure this is their expected behavior, on their locked down devices, I would work under the assumption that this isn't going away. This is probably different for native iOS apps. Definitely keep the form autocomplete="off" and hopefully they'll one day get back to the HTML5 standard for the feature.
I know this doesn't include any work around, but I think if you come to terms with it being a non-browser 'feature' on iDevices, it makes sense (in an Apple kind of way).
回答6:
This question has already been successfully answered, but as of today's date, the solution didn't work for me without making some oddly particular changes - so I'm noting it here as much for my own reference if I decide to come back to it as for everyone else's.
- The fake input needs to be after the real email input in the dom.
- The fake input requires a fake label.
- The fake label cannot be absolutely positioned.
- Can't use display, visibility or opacity to hide the fake elements.
The only solution I found was to clip the visibility of the fake elements with overflow: hidden
.
<label for="user_email">Email</label>
<input autocomplete="off" type="text" value="user@email.com" name="user[email]" id="user_email">
<!-- Safari looks for email inputs and overwrites the existing value with the user's personal email. This hack catches the autofill in a hidden input. -->
<label for="fake_email" aria-hidden="true" style="height: 1px; width: 1px; overflow: hidden; clip: rect(1px, 1px, 1px, 1px)">Email</label>
<input type="text" name="fake[email]" id="fake_email" style="height: 1px; width: 1px; overflow: hidden; clip: rect(1px, 1px, 1px, 1px)" tab-index="-1" aria-hidden="true">
For the record, the particular case this hack came in useful for was one where an admin is editing the profile of other users and Safari was replacing the email of the user with the email of the admin. We've decided that for the small (but frustrating) amount of support requests that this Safari 'feature' creates, it's not worth maintaining a hack that seems to need to evolve as Safari tightens up on it, and instead provide support to those users on how to turn off autofill.
回答7:
I can't believe this is still an issue so long after it's been reported. The above solutions didn't work for me, as safari seemed to know when the element was not displayed or off-screen, however the following did work for me:
<div style="position:absolute;height:0px; overflow:hidden; ">
Username <input type="text" name="fake_safari_username" >
Password <input type="password" name="fake_safari_password">
</div>
Hope that's useful for somebody!
回答8:
I have also been bitten by Safari's weird default autocomplete behaviour, but rather than completely disable it, I managed to make it work for me by following the guidelines at https://www.chromium.org/developers/design-documents/form-styles-that-chromium-understands.
Specifically, I put autocomplete="username"
on the username field and autocomplete="password-current"
on the password field. This tells the browser which fields to autofill, rather than having it guess, and it fixed autocomplete for my use case.
This approach works for both "email first" login forms (password field not immediately visible, eg Google login) as well as conventional login forms with both username and password fields visible.
回答9:
You can try this variant. It works for me.
If you change field value once, Safari will change it again. If user clicked at this field, after this the value wouldn't be changed by Safari automatically.
$.browser.chrome = /chrome/.test(navigator.userAgent.toLowerCase());
if($.browser.chrome){
$.browser.safari = false;
}
var isChanged=false;
$('#Email').change(function () {
if ($.browser.safari && !isChanged) {
$('#Email').val('@Model.Email');
}
});
$('#Email').click(function () {
if ( $.browser.safari && !isChanged) {
isChanged = true;
}
}); var isChangePassword = false;
$('#OldPassword').change(function () {
if ($.browser.safari && !isChangePassword) {
$('#OldPassword').val('');
}
});
$('#OldPassword').click(function () {
if ($.browser.safari && !isChangePassword) {
isChangePassword= true;
}
});
回答10:
It seems the browser programmers think they know more than the website writers. While it's sometimes handy to allow the user to save passwords, there are other times when it's a security risk. For those times, this workaround might help:
Start by using a conventional text input, instead of a 'password' type.
Password:   <input type="text" id="fkpass" name="bxpass" class="tinp" size="20" />
Then - if you wish - set the focus to the input field.
<BODY onLoad="fitform()">
Put the JS at the end of the page.
<script type="text/javascript">
document.entry.fkpass.focus();
function fitform() {
document.getElementById('fkpass').autocomplete = 'off';
}
</script>
Now you have a conventional form field. What good is that?
Change the CSS style for that input so it uses a font that is all 'bullets' instead of characters.
<style type="text/css">
@font-face { font-family: fdot; src: url('images/dot5.ttf'); }
@font-face { font-family: idot; src: url('images/dot5.eot'); }
@font-face { font-family: wdot; src: url('images/dot5.woff'); }
@font-face { font-family: w2dot; src: url('images/dot5.woff2'); }
.tinp { font-family: fdot, idot, wdot, w2dot; color: #000; font-size:18px; }
</style>
Yes, you could 'tidy up' the code, and add .svg to it.
Either way, the end result is indistinguishable from the 'real' password input, and the browser won't offer to save it.
If you want the font, it's here.
It was created with CorelDraw and converted with an online webfont conversion utility. (dot_webfont_kit.zip 19.3k)
I hope this helps.
回答11:
Remove <form>
element. To keep form behavior you can listen keypress
event for input fields to handle enter
key pressed. Just in case I removed input type="submit"
too. You can use button type="button"
.
回答12:
Better than use JS to clear content - simply fake password field:
<input type="text" name="user" />
<input fake_pass type="password" style="display:none"/>
<input type="password" name="pass" />
A password
type doubled put the browser in incertitude so it autocompletes only user name
fake_pass
input
should not have name
attribute to keep $_POST
clean!
回答13:
My issue: I have a section in an admin area that allows users to set all language values, some of which contain the words "password", "email", "email address" etc. I don't want these values to be filled with the user's details, they are for creating translations into another language. This is then a valid exception to the "circumvent the browser's preference" mentioned.
My solution: I simply created alternate names:
$name = str_replace('email','em___l',$name);
$name = str_replace('password','pa___d',$name);
<input type="text" name="<?=$name?>" id="<?=$name?>" />
Then when the form is posted:
foreach($_POST as $name=>$value) {
$name=str_replace('em___l','email',$name);
$name=str_replace('pa___d','password',$name);
$_POST[$name]=$value;
}
This is the only method that worked for me.
回答14:
The CSS display: none
solutions mentioned here did not work for me (October 2016). I fixed this issue with JavaScript.
I don't mind the browser remembering passwords, but wanted to prevent a bad autofill. In my case, a form with a password field and no associated username field. (User edit form in Drupal 7 site, where the password field is required only for some operations.) Whatever I tried, Safari would find a victim field for the username of the autofilled password (the field placed visually before, for instance).
I'm restoring the original value as soon as Safari does the autofill. I'm trying this only for the first 2 seconds after page load. Probably even lower value is OK. My tests showed the autofill happens around 250 ms after page load (though I imagine this number depends a lot on how the page is constructed and loaded).
Here's my JavaScript code (with jQuery):
// Workaround for Safari autofill of the e-mail field with the username.
// Try every 50ms during 2s to reset the e-mail to its original value.
// Prevent this reset if user might have changed the e-mail himself, by
// detecting focus on the field.
if ($('#edit-mail').length) {
var element = $('#edit-mail');
var original = element.attr('value');
var interval = setInterval(function() {
if ($(document.activeElement).is(element)) {
stop();
} else if (element.val() != original) {
element.val(original);
stop();
}
}, 50);
var stop = function() {
clearTimeout(timeout);
clearInterval(interval);
}
var timeout = setTimeout(function() {
clearInterval(interval);
}, 2000);
}
回答15:
I had the same problem suddenly in a SPA with React in Mobile Safari 10.3.1
I do not need any tricky workarounds before in all tested browsers, even Mobile Safari IOS 10.2
But since 10.3.1 username or password will be filled in fields mentioning the words 'password','email','username' in any forms after login with active remember option. It seems that the rendered DOM-Tree is 'analyzed' using a full text search and then the user agent fill in data without respecting any autocomplete="off" setting.
Happens funnyli also on placeholder text for a field. So you must be very carful with naming, when you don't want to have prefilled username or password in places where this data is not useful.
The only solution after hours of investigating was the solution here posted too.
Provide a input field named "email" and hideout the containing div with height: 0px, overflow: hidden.