Вопрос или проблема
Мне нужно запретить браузерам сохранять значения имени пользователя и пароля, потому что я работаю над веб-приложением, содержащее более защищенные данные. Мой клиент попросил меня сделать это.
Я попробовал атрибут autocomplete="off"
в HTML-форме и полях для паролей. Но он не работает в последних браузерах, таких как Chrome 55, Firefox 38+, Internet Explorer 11 и т. д.
Какое лучшее решение для этого?
Спасибо за ваш ответ. Я следовал по приведенной ниже ссылке
Отключение функции сохранения пароля в браузере
Я решил проблему, добавив атрибуты readonly
и onfocus="this.removeAttribute('readonly');"
наряду с autocomplete="off"
к полям ввода, как показано ниже.
<input type="text" name="UserName" autocomplete="off" readonly
onfocus="this.removeAttribute('readonly');" >
<input type="password" name="Password" autocomplete="off" readonly
onfocus="this.removeAttribute('readonly');" >
Это работает отлично для меня.
Попытка предотвратить сохранение паролей в браузере не рекомендуется. Существуют некоторые обходные пути, которые могут это сделать, но современные браузеры не предоставляют эту функцию «из коробки» и по вполне обоснованным причинам. Современные браузеры хранят пароли в менеджерах паролей, чтобы пользователи могли использовать более сложные пароли, чем обычно.
Как объясняется в MDN: Как отключить автозаполнение форм:
Современные браузеры реализуют интегрированное управление паролями: когда пользователь вводит имя пользователя и пароль для сайта, браузер предлагает запомнить их. Когда пользователь снова посещает сайт, браузер автоматически заполняет поля входа сохраненными значениями.
Кроме того, браузер позволяет пользователю выбрать мастер-пароль, который будет использоваться для шифрования сохраненных данных входа.
Даже без мастер-пароля управление паролями в браузере обычно рассматривается как чистая выгода для безопасности. Поскольку пользователям не нужно запоминать пароли, которые браузер хранит за них, они могут выбирать более сложные пароли, чем в противном случае.
По этой причине многие современные браузеры не поддерживают
autocomplete="off"
для полей входа:
Если сайт устанавливает
autocomplete="off"
для формы, и форма содержит поля ввода имени пользователя и пароля, браузер по-прежнему предложит запомнить этот логин, и если пользователь согласится, браузер автоматически заполнит эти поля в следующий раз, когда пользователь посетит страницу.Если сайт устанавливает
autocomplete="off"
для полей ввода имени пользователя и пароля, браузер по-прежнему предложит запомнить этот логин, и если пользователь согласится, браузер автоматически заполнит эти поля в следующий раз, когда пользователь посетит страницу.Такое поведение наблюдается в Firefox (начиная с версии 38), Google Chrome (начиная с версии 34) и Internet Explorer (начиная с версии 11).
Если автор хочет предотвратить автозаполнение полей пароля на страницах управления пользователями, где пользователь может указать новый пароль для кого-то, кроме себя, следует указать
autocomplete="new-password"
, хотя поддержка этого везде еще не реализована.
Вот чистое HTML/CSS решение для Chrome, протестированное в версии 65.0.3325.162 (официальная сборка) (64-битная).
Установите ввод type="text"
и используйте CSS text-security:disc
, чтобы имитировать type="password"
.
<input type="text" name="username">
<input type="text" name="password" style="text-security:disc; -webkit-text-security:disc;" autocomplete="off">
- Примечание: работает в Firefox, но CSS
moz-text-security
устарел/устранен. Чтобы исправить это, создайте CSSfont-face
, состоящий только из точек, и используйтеfont-family: 'dotsfont';
.
Источник:
Получить input type=text, чтобы выглядеть как type=password
Указанный источник содержит ссылку на обходной путь для CSS moz-text-security
и -webkit-text-security
свойств.
Источник: https://github.com/kylewelsby/dotsfont
Насколько я тестировал, это решение работает для Chrome, Firefox версии 59.0 (64-бит), Internet Explorer версии 11.0.9600 и эмуляторов IE Internet Explorer 5 и выше.
Правка безопасности 2023: Я добавил атрибут autocomplete="off"
к вводу пароля. Установив autocomplete="off"
, вы инструктируете браузер не заполнять и не запоминать значения для этого конкретного поля ввода.
Важно отметить, что хотя большинство современных браузеров уважают атрибут autocomplete="off"
, некоторые браузеры могут игнорировать его по соображениям безопасности или предлагать пользователю возможность переопределить настройку. Кроме того, разные браузеры могут трактовать атрибут по-разному, так что это не надежное решение.
Я решил эту проблему, добавив autocomplete="one-time-code"
к вводу пароля.
Согласно справочнику по HTML autocomplete="one-time-code"
– это одноразовый код, используемый для проверки идентичности пользователя. Это выглядит наиболее подходящим для этой ситуации.
Вы можете создать скрытое текстовое поле для пароля, чтобы предотвратить это.
<form>
<div style="display:none">
<input type="password" tabindex="-1"/>
</div>
<input type="text" name="username" placeholder="имя пользователя"/>
<input type="password" name="password" placeholder="пароль"/>
</form>
</div><div class="s-prose js-post-body" itemprop="text">
По умолчанию нет правильного ответа для отключения сохранения пароля в вашем браузере. Но к счастью, существует обходной путь, который работает почти во всех браузерах.
Для этого добавьте фиктивный ввод непосредственно перед фактическим полем с autocomplete="off"
и некоторым пользовательским стилем, чтобы скрыть его и указать tabIndex.
<pАвтозаполнение некоторых браузеров (Chrome) заполнит первое поле для пароля, которое он найдет, и поле перед ним, так что с помощью этого трюка оно заполнит только невидимое поле, которое не имеет значения.
<div className="password-input">
<input
type="password"
id="prevent_autofill"
autoComplete="off"
style={{
opacity: '0',
position: 'absolute',
height: '0',
width: '0',
padding: '0',
margin: '0'
}}
tabIndex="-2"
/>
<input
type="password"
autoComplete="off"
className="password-input-box"
placeholder="Пароль"
onChange={e => this.handleChange(e, 'password')}
/>
</div>
</div><div class="s-prose js-post-body" itemprop="text">
Я протестировал многие решения и в конечном итоге пришел к этому решению.
HTML код
<input type="text" name="UserName" id="UserName" placeholder="Имя пользователя" autocomplete="off" />
<input type="text" name="Password" id="Password" placeholder="Пароль" autocomplete="off"/>
CSS код
#Password {
text-security: disc;
-webkit-text-security: disc;
-moz-text-security: disc;
}
JavaScript код
window.onload = function () {
init();
}
function init() {
var x = document.getElementsByTagName("input")["Password"];
var style = window.getComputedStyle(x);
console.log(style);
if (style.webkitTextSecurity) {
// Ничего не делать
} else {
x.setAttribute("type", "password");
}
}
</div><div class="s-prose js-post-body" itemprop="text">
На момент публикации ни одно из предыдущих ответов мне не помогло.
Этот подход использует видимое поле для пароля, чтобы захватить пароль от пользователя, и скрытое поле для пароля, чтобы передать пароль на сервер. Видимое поле для пароля очищается перед отправкой формы, но не с помощью обработчика события submit
(см. объяснение в следующем абзаце). Этот подход переносит значение видимого поля для пароля в скрытое поле для пароля как можно скорее (без ненужных затрат) и затем очищает видимое поле для пароля. Если пользователь снова перемещается к видимому полю для пароля, значение восстанавливается. Он использует плейсхолдер для отображения ●●● после того, как поле было очищено.
Я пытался очистить видимое поле для пароля при событии onsubmit
формы, но, похоже, браузер проверяет значения перед обработчиком события и предлагает пользователю сохранить пароль. На самом деле, если alert
в конце passwordchange
закомментировать, браузер по-прежнему предложит сохранить пароль.
function formsubmit(e) {
document.getElementById('form_password').setAttribute('placeholder', 'пароль');
}
function userinputfocus(e) {
// Просто чтобы сделать поле имени пользователя обязательным
// как и поле пароля.
e.target.value = e.target.value;
}
function passwordfocus(e) {
e.target.setAttribute('placeholder', 'пароль');
e.target.setAttribute('required', 'required');
e.target.value = document.getElementById('password').value;
}
function passwordkeydown(e) {
if (e.key === 'Enter') {
passwordchange(e.target);
}
}
function passwordblur(e) {
passwordchange(e.target);
if (document.getElementById('password').value !== '') {
var placeholder="";
for (i = 0; i < document.getElementById('password').value.length; i++) {
placeholder = placeholder + '●';
}
document.getElementById('form_password').setAttribute('placeholder', placeholder);
} else {
document.getElementById('form_password').setAttribute('placeholder', 'пароль');
}
}
function passwordchange(password) {
if (password.getAttribute('placeholder') === 'пароль') {
if (password.value === '') {
password.setAttribute('required', 'required');
} else {
password.removeAttribute('required');
var placeholder="";
for (i = 0; i < password.value.length; i++) {
placeholder = placeholder + '●';
}
}
document.getElementById('password').value = password.value;
password.value="";
// Этот alert заставит браузер предложить сохранить пароль
// alert(e.type);
}
}
#form_password:not([placeholder="пароль"])::placeholder {
color: red; /* изменить на черный */
opacity: 1;
}
<form onsubmit="formsubmit(event)" action="/action_page.php">
<input type="hidden" id="password" name="password" />
<input type="text" id="username" name="username" required
autocomplete="off" placeholder="имя пользователя"
onfocus="userinputfocus(event)" />
<input type="password" id="form_password" name="form_password" required
autocomplete="off" placeholder="пароль"
onfocus="passwordfocus(event)"
onkeydown="passwordkeydown(event)"
onblur="passwordblur(event)"/>
<br />
<input type="submit"/>
< input type="password" style="pointer-event: none" onInput= (e) => handleInput(e) />
function handleInput(e) {
e.preventDefault();
e.stopPropagation();
e.target.setAttribute('readonly', true);
setTimeout(() => {
e.target.focus();
e.target.removeAttribute('readonly');
});
}
Я создаю PWA с использованием React. (И использую Material-UI и Formik в рассматриваемом компоненте, поэтому синтаксис может показаться немного необычным…)
Я хотел остановить Chrome от попыток сохранить учетные данные для входа (поскольку устройства совместно используются многими пользователями в моей ситуации).
Для ввода (сейчас это MUI TextField) я установил type на “text”, а не на “password”, чтобы обойти обнаружение функции хранения учетных данных в Chrome. Я сделал input-mode равным “numeric”, чтобы клавиатура открывалась как клавиатура, потому что пользователи будут вводить ПИН для своего пароля.
А затем, как и другие здесь описывали, я использовал text-security: disc; и -webkit-text-security: disc;
Снова обращаю ваше внимание на синтаксис моего кода, так как используется React, MUI и т. д. (React использует заглавные буквы и без дефисов и т. д.)
Вот части с комментариями //; остальное – это просто дополнительная информация для контекста.
<TextField
type="text" // это хитрость, чтобы Chrome не предлагал сохраненные учетные данные; в противном случае должен быть "password"
name="pincode"
placeholder="пин"
value={values[PIN_FIELD]}
onChange={handleChange}
onBlur={handleBlur}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<RemoveRedEye
color="action"
onClick={togglePasswordMask}
/>
</InputAdornment>
),
inputProps: {
inputMode: 'numeric', // для числовой клавиатуры
style: {
textSecurity: `${passwordIsMasked ? 'disc' : ''} `, // часть хитрости, описанной выше. этот диск имитирует видимость пароля ***
WebkitTextSecurity: `${passwordIsMasked ? 'disc' : ''} `, // та же хитрость
},
},
}}
/>
Как вы видите, у меня есть переключатель, который позволяет скрывать или отображать пин-код (нажав на значок глаза). Подобную функцию можно добавить по мере необходимости.
const [passwordIsMasked, setPasswordIsMasked] = useState(true)
const togglePasswordMask = () => {
setPasswordIsMasked((value) => !value)
}
Вот чистое html/css (без js) решение
- Для input/type=text используйте textarea
- Для пароля используйте textarea с шрифтом круглыми значками (см. https://stackoverflow.com/a/40982531/146457)
<textarea required="required" autocorrect="off" autocapitalize="off" name="username" class="form-control" placeholder="Ваше имя пользователя" rows="1" cols="20" wrap="off"></textarea>
<textarea required="required" autocorrect="off" autocapitalize="off" name="password" class="form-control password" placeholder="Ваш пароль" rows="1" cols="20" wrap="off"></textarea>
@font-face {
font-family: 'password';
src: url('css/font/password.woff2') format('woff2'),
url('css/font/password.woff') format('woff'),
url('css/font/password.ttf') format('truetype');
font-weight: normal;
font-style: normal;
}
textarea.form-control {
overflow:hidden;
resize:none;
height:34px;
}
textarea.form-control.password:valid {
font-family: 'password';
}
Примечания
- Textarea предотвращает автозаполнение и срабатывание менеджера паролей
- wrap=off/overlow=hidden/rows=1 заставляют отображаться в одну строку
- псевдокласс required делает плейсхолдер активным
- Вам, вероятно, потребуется что-то типа “предотвратить событиеKey=13 / отправить”
- Работает отлично в firefox/chrome/iOS
В конечном итоге это оказалось чертовски бесполезным набором хаков (но это работает)
Это сработало для меня:
<form action='/login' class="login-form" autocomplete="off">
Пользователь:
<input type="user" name="user-entry">
<input type="hidden" name="user">
Пароль:
<input type="password" name="password-entry">
<input type="hidden" name="password">
</form>
Я думаю, что это невозможно в последних браузерах.
Единственный способ, которым вы можете это сделать, – это взять другое скрытое поле пароля и использовать его для своей логики после получения значения из видимого поля пароля при отправке, а затем вставить фиктивную строку в видимое поле пароля.
В этом случае браузер может сохранить фиктивную строку вместо фактического пароля.
Попробуйте следующее. Это может вам помочь.
Для получения дополнительной информации посетите Тип ввода=пароль, не позволяйте браузеру запоминать пароль
function setAutoCompleteOFF(tm) {
if(typeof tm == "undefined") {
tm = 10;
}
try {
var inputs = $(".auto-complete-off, input[autocomplete=off]");
setTimeout(function() {
inputs.each(function() {
var old_value = $(this).attr("value");
var thisobj = $(this);
setTimeout(function() {
thisobj.removeClass("auto-complete-off").addClass("auto-complete-off-processed");
thisobj.val(old_value);
}, tm);
});
}, tm);
}
catch(e){
}
}
$(function(){
setAutoCompleteOFF();
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="passfld" type="password" autocomplete="off" />
<input type="submit">
Один из способов – генерировать случайные имена вводов и работать с ними.
Таким образом, браузеры будут получать new
форму каждый раз и не смогут предзаполнить поля ввода.
Если вы предоставите нам какой-то пример кода (есть ли у вас JavaScript одностраничное приложение (SPA) или рендеринг на стороне сервера), я буду рад помочь вам в реализации.
Несколько лет назад мне это нужно было для конкретной ситуации: два человека, которые знают свои сетевые пароли, одновременно получают доступ к одной машине, чтобы подписать юридическое соглашение.
Вы не хотите, чтобы какой-либо пароль был сохранен в этой ситуации, потому что сохранение пароля является юридической проблемой, не технической, и присутствие обоих людей как физически, так и во времени обязательно. Теперь я соглашусь, что это редкая ситуация, но такие ситуации существуют, и встроенные менеджеры паролей в веб-браузерах бесполезны.
Мое техническое решение выше заключалось в переключении между password
и text
типами и в том, чтобы сделать цвет фона таким же, как цвет текста, когда поле является обычным текстовым полем (тем самым продолжая скрывать пароль). Браузеры не запрашивают сохранение паролей, которые хранятся в текстовых полях.
Плагин jQuery:
Соответствующий исходный код из приведенной выше ссылки:
(function($) {
$.fn.StopPasswordManager = function() {
return this.each(function() {
var $this = $(this);
$this.addClass('no-print');
$this.attr('data-background-color', $this.css('background-color'));
$this.css('background-color', $this.css('color'));
$this.attr('type', 'text');
$this.attr('autocomplete', 'off');
$this.focus(function() {
$this.attr('type', 'password');
$this.css('background-color', $this.attr('data-background-color'));
});
$this.blur(function() {
$this.css('background-color', $this.css('color'));
$this.attr('type', 'text');
$this[0].selectionStart = $this[0].selectionEnd;
});
$this.on('keydown', function(e) {
if (e.keyCode == 13)
{
$this.css('background-color', $this.css('color'));
$this.attr('type', 'text');
$this[0].selectionStart = $this[0].selectionEnd;
}
});
});
}
}(jQuery));
Демо:
https://barebonescms.com/demos/admin_pack/admin.php
Нажмите “Добавить запись” в меню, а затем прокрутите вниз страницы до “Модуля: Остановить менеджер паролей”.
Одно из того, что вы можете сделать, это попросить ваших пользователей отключить сохранение пароля для вашего сайта. Это можно сделать для всего браузера или для источника.
Что-то еще, что вы можете сделать, это заставить поля ввода быть пустыми после загрузки страницы (и после того, как браузер автоматически заполнил поля). Поместите этот скрипт в конец элемента <body>
.
userIdInputElement.value = "";
userPasswordInputElement.value = "";
Я бы создал переменную сессии и сгенерировал ее случайным образом. Затем построил бы id и name значения на основе переменной сессии. Затем при входе опросите созданную вами переменную сессии.
if (!isset($_SESSION['autoMaskPassword'])) {
$bytes = random_bytes(16);
$_SESSION['autoMask_password'] = bin2hex($bytes);
}
<input type="password" name="<?=$_SESSION['autoMaskPassword']?>" placeholder="пароль">
В такой ситуации я заполняю поле пароля случайными символами сразу после того, как оригинальный пароль будет получен внутренним JavaScript кодом, но сразу перед отправкой формы.
ПРИМЕЧАНИЕ: Фактический пароль будет, безусловно, использован для следующего шага формы. Значение сначала передается в скрытое поле. См. пример кода.
Таким образом, когда менеджер паролей браузера сохраняет пароль, это не настоящий пароль, который пользователь ввел. Таким образом, пользователь думает, что пароль был сохранен, хотя на самом деле сохранено что-то случайное. Со временем пользователь поймет, что он/она не может доверять менеджеру паролей, чтобы выполнять свою работу для этого сайта.
Теперь это может привести к плохому пользовательскому опыту; я знаю, потому что пользователь может почувствовать, что браузер действительно сохранил пароль. Но с адекватной документацией пользователь может быть успокоен. Я считаю, что это способ полностью убедиться, что фактический пароль, введенный пользователем, не может быть захвачен браузером и сохранен.
<form id='frm' action="https://google.com">
Пароль: <input type="password" id="pwd" />
<input type="hidden" id='hiddenpwd' />
<button onclick='subm()'>Отправить</button>
</form>
<script>
function subm() {
var actualpwd = $('#pwd').val();
$('#hiddenpwd').val(actualpwd);
// ... Выполните любые действия с фактическим паролем
// ... Или присвойте значение другому скрытому полю
$('#pwd').val('globbedygook');
$('#frm').submit();
}
</script>
Я сделал это, установив атрибут типа поля пароля в “скрытый” перед событием клика:
document.getElementById("password").setAttribute("type", "hidden");
document.getElementById("save").click();
Поле ввода пароля по сути заменяет символы.
1. Скачайте шрифт https://pan.baidu.com/s/1TnlCRB8cam6KgS6OarXu3w (c23n)
2.
<style>
@font-face {
font-family: 'htmlpassword';
font-style: normal;
font-weight: 300;
src: url(./css/fonts/htmlpassword.woff2) format('woff2');
}
</style>
<input type="text" autocomplete="off" name="password" style="font-family: "htmlpassword";">
Попробуйте
<input type="password" placeholder="Введите пароль" autocomplete="new-password">
autocomplete="new-password"
работает для меня.
Ответ или решение
Вопрос о том, как предотвратить браузеры от сохранения паролей, является актуальным для веб-разработчиков, особенно когда речь идет о работе с конфиденциальной информацией. К сожалению, нет однозначного способа полностью запретить браузерам хранить пароли, так как современные браузеры имеют встроенные менеджеры паролей, которые могут игнорировать специальные атрибуты HTML в некоторых случаях. Однако, есть несколько решений, которые могут помочь в решении этой проблемы.
1. Использование атрибута autocomplete
Ранее стандартный подход к отключению автозаполнения заключался в использовании атрибута autocomplete="off"
в элементах формы. Тем не менее, современные браузеры, такие как Google Chrome и Firefox, игнорируют этот атрибут для полей ввода паролей и имен пользователей.
Пример:
<input type="text" name="username" autocomplete="off" />
<input type="password" name="password" autocomplete="off" />
2. Альтернативная обработка поля
Некоторые разработчики используют следующие обходные пути:
-
Использовать свойства
readonly
в сочетании с JavaScript, чтобы отключить ввод до тех пор, пока поле не получит фокус:<input type="text" name="username" autocomplete="off" readonly onfocus="this.removeAttribute('readonly');" /> <input type="password" name="password" autocomplete="off" readonly onfocus="this.removeAttribute('readonly');" />
-
Создание невидимого поля с атрибутом
autocomplete="off"
, чтобы браузеры заполняли его вместо видимого поля:<input type="password" name="dummy" style="display:none;" autocomplete="off" /> <input type="password" name="password" autocomplete="off" />
3. Модификация вида полей ввода
Другой подход, который может помочь, заключается в использовании текстовых полей вместо полей пароля, а также в изменении типа поля с "password" на "text" для предотвращения автоматического сохранения пароля:
<input type="text" name="password" onfocus="this.type='password';" onblur="this.type='text';" />
4. Использование JavaScript для динамического управления вводом
Можно создать функцию, которая будет управлять поведением полей ввода. Например, при вводе символов можно скрывать их или заменять:
document.getElementById('password').addEventListener('keydown', function(event) {
// Обработка нажатия клавиш
});
5. Отказ от стандартных методов
Иногда разработчики используют нестандартные поля ввода, такие как текстовые области (<textarea>
), чтобы обойти стандартное поведение браузеров. Однако этот подход может создать проблемы с доступностью и пользовательским опытом.
Заключение
Несмотря на существующие обходные пути, важно понимать, что использование методов для предотвращения сохранения паролей может негативно сказаться на пользовательском опыте. Современные браузеры предлагают функции управления паролями для повышения безопасности, что в целом является позитивным моментом. Перед применением указанных методов обязательно оцените их влияние на вашу аудиторию и целесообразность использования в вашем конкретном случае.