如何防止浏览器存储密码

时间:2016-12-19 06:39:58

标签: html security browser gxt

我需要阻止浏览器存储用户名&密码值,因为我正在处理包含更多安全数据的Web应用程序。我的客户要我这样做。

我尝试了HTML表单中的autocomplete="off"属性&密码字段。但它不适用于最新的浏览器,如Chrome 55,Firefox 38 +,IE 11等等。

最佳解决方案是什么?

26 个答案:

答案 0 :(得分:30)

这在现代浏览器中是不可能的,并且有充分的理由。现代浏览器提供密码管理器,使用户能够使用比通常更强的密码。

正如MDN: How to Turn Off Form Autocompletion所述:

  

现代浏览器实现集成密码管理:当用户输入网站的用户名和密码时,浏览器会为用户记住它。当用户再次访问该站点时,浏览器会使用存储的值自动填充登录字段。

     

此外,浏览器允许用户选择浏览器将用于加密存储的登录详细信息的主密码。

     

即使没有主密码,浏览器内密码管理通常被视为安全性的净增益。由于用户不必记住浏览器为其存储的密码,因此他们可以选择比其他方式更强的密码。

     

出于这个原因,许多现代浏览器不支持登录字段autocomplete="off"

     
      
  • 如果网站为表单设置了autocomplete="off",并且表单包含用户名和密码输入字段,那么浏览器仍会提供记住此登录信息,如果用户同意,浏览器将自动填充下次用户访问该页面时会显示这些字段。

  •   
  • 如果网站为用户名和密码输入字段设置autocomplete="off",则浏览器仍会提供记住此登录信息,如果用户同意,则浏览器将在下次用户时自动填充这些字段访问该页面。

  •   
     

这是Firefox(自版本38以来),Google Chrome(自34版)和Internet Explorer(自版本11以来)以来的行为。

     

如果作者想要阻止用户管理页面中的密码字段自动填充,用户可以为自己以外的其他人指定新密码,则应指定autocomplete="new-password",但是尚未对此进行支持在所有浏览器中。

答案 1 :(得分:26)

感谢您回复我。我按照以下链接

Disable browser 'Save Password' functionality

我只是添加了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');" >

这对我来说很好。

答案 2 :(得分:9)

我通过在密码输入中添加autocomplete="one-time-code"来解决此问题。

根据an HTML reference autocomplete="one-time-code"-用于验证用户身份的一次性代码。看起来最适合这个。

答案 3 :(得分:6)

以下是在版本65.0.3325.162(官方版本)(64位)中测试 Chrome 的纯 HTML / CSS 解决方案。

设置输入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;">
  • 注意:适用于 FireFox ,但 CSS moz-text-security是 弃用/删除。要解决此问题,请创建一个仅由 CSS font-face组成的 点和使用font-family: 'dotsfont';

      

    来源:   Get input type=text to look like type=password

    上面的来源包含指向 CSS moz-text-security-webkit-text-security属性的解决方法的链接。

      

    来源:https://github.com/kylewelsby/dotsfont

    据我测试,此解决方案适用于 Chrome FireFox版本59.0(64位) IE版本11.0.9600 以及 IE模拟器ie5 和更高。

答案 4 :(得分:4)

你应该可以制作一个假的隐藏密码框来阻止它。

<form>
  <div style="display:none">
    <input type="password" tabindex="-1"/>
  </div>
  <input type="text" name="username" placeholder="username"/>
  <input type="password" name="password" placeholder="password"/>
</form>

答案 5 :(得分:3)

我测试了许多解决方案,最后我想到了这个解决方案。

HTML代码

<input type="text" name="UserName" id="UserName" placeholder="UserName" autocomplete="off" />
<input type="text" name="Password" id="Password" placeholder="Password" 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) {
        // Do nothing
    } else {
        x.setAttribute("type", "password");
    }
}

答案 6 :(得分:2)

发布此消息时,以前的答案都对我没有帮助。

此方法使用可见的密码字段来捕获用户的密码,并使用隐藏的密码字段来将密码传递给服务器。提交表单之前,可见密码字段为空白,但没有表单submit事件处理程序(请参阅下一段的说明)。此方法将可见密码字段值尽快(没有不必要的开销)传输到隐藏密码字段,然后清除可见密码字段。如果用户跳回到可见的密码字段,则将恢复该值。清除字段后,它将使用占位符显示●●●。

我尝试清除表单onsubmit事件上的可见密码字段,但浏览器似乎正在检查事件处理程序之前的值,并提示用户保存密码。实际上,如果未注释alert末尾的passwordchange,浏览器仍会提示您保存密码。

function formsubmit(e) {
  document.getElementById('form_password').setAttribute('placeholder', 'password');
}

function userinputfocus(e) {
  //Just to make the browser mark the username field as required
  // like the password field does.
  e.target.value = e.target.value;
}

function passwordfocus(e) {
  e.target.setAttribute('placeholder', 'password');
  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', 'password');
  }
}

function passwordchange(password) {
  if (password.getAttribute('placeholder') === 'password') {
    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 = '';

    //This alert will make the browser prompt for a password save
    //alert(e.type);
  }
}
#form_password:not([placeholder='password'])::placeholder {
  color: red; /*change to black*/
  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="username"
  onfocus="userinputfocus(event)" />
<input type="password" id="form_password" name="form_password" required
  autocomplete="off" placeholder="password"
  onfocus="passwordfocus(event)"
  onkeydown="passwordkeydown(event)"
  onblur="passwordblur(event)"/>
<br />
<input type="submit"/>

答案 7 :(得分:2)

默认情况下,没有正确的答案来禁用在浏览器中保存密码。但幸运的是,有一种解决方法,它几乎可以在所有浏览器上使用。

要实现此目的,请在带有autocomplete =“ off”的实际输入之前添加一个虚拟输入,并使用一些自定义样式将其隐藏并提供tabIndex。 浏览器的(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="Password"
              onChange={e => this.handleChange(e, 'password')}
            />
          </div>

答案 8 :(得分:1)

我正在使用 React 制作 PWA。 (并且在有问题的组件上使用 Material-UI 和 Formik,所以语法可能看起来有点不寻常......)

我想阻止 Chrome 尝试保存登录凭据(因为在我的情况下,设备与许多用户共享)。

对于输入(在我的例子中为 MUI TextField),我将 type 设置为 "text" 而不是“password”,以便绕过 Chromes 检测存储凭证功能。我将 input-mode 设为 "numeric" 以使小键盘作为键盘弹出,因为用户将输入 PIN 作为他们的密码。 然后,正如这里的其他人所描述的,我使用了 text-security: disc;-webkit-text-security: disc;
再次注意我的代码的语法,因为它使用的是 React、MUI 等(React 使用大写字母,没有破折号等)

查看带有 // 注释的部分;其余的只是上下文的奖励。

<TextField
            type="text" // this is a hack so Chrome does not offer saved credentials; should be "password" otherwise
            name="pincode"
            placeholder="pin"
            value={values[PIN_FIELD]}
            onChange={handleChange}
            onBlur={handleBlur}
            InputProps={{
              endAdornment: (
                <InputAdornment position="end">
                  <RemoveRedEye
                    color="action"
                    onClick={togglePasswordMask}
                  />
                </InputAdornment>
              ),
              inputProps: {
                inputMode: 'numeric', // for number keyboard
                style: {
                  textSecurity: `${passwordIsMasked ? 'disc' : ''} `, // part of hack described above. this disc mimics the password *** appearance
                  WebkitTextSecurity: `${passwordIsMasked ? 'disc' : ''} `, // same hack
                },
              },
            }}
          />

如您所见,我有一个切换按钮,可让您隐藏或显示图钉(通过单击眼睛图标)。可以根据需要/需要添加类似的功能。

const [passwordIsMasked, setPasswordIsMasked] = useState(true)
const togglePasswordMask = () => {
setPasswordIsMasked((value) => !value)

}

答案 9 :(得分:0)

这是我1天前的解决方案(自发布之日起) 它将侦听器添加到选定的密码ID,并且不依赖于Webkit特定CSS规则的隐藏表单字段。

我不得不在此处粘贴代码,但是查看Fiddler版本以获取完整的HTML和说明。

https://jsfiddle.net/AdamWhateverson/hLbztn0a/

  <script type="text/javascript" id="pwsremover" data-fieldid="my_password">
  if (document.addEventListener) {
    var _PWH = {
      selected: false,
      touched: true,
      init: function() {

        // The script must always have the id of 'pwsremover'
        var pw = document.getElementById('pwsremover');

        // You need set the 'data-fieldid' attribute on the script tag to ensure
        // the id of your password input field is passwed in
        var fi = pw.dataset.fieldid;

        // Convert password to text type
        var ff = document.getElementById(fi);
        ff.type="text";
        var h = ff.outerHTML+"";
        ff.outerHTML = h;

        // Attach event handlers
        var passSelected = false
        document.addEventListener("selectionchange", function(ev) {
          var ae = ev.target.activeElement;
          if (ae.id == "login_pass") {
            var kc = ev.keyCode;
            var ss = ae.selectionStart;
            var se = ae.selectionEnd;
            var sl = Math.max(ae.selectionStart, ae.selectionEnd);
            var il = ae.value.length;
            _PWH.selected = (ss == 0 && se > 0 && sl == il) || ((kc == 8 || kc == 46) && il == 1);
          }
        });
        var el = document.getElementById(fi);
        el.addEventListener("keydown", function(ev) {
          if (((ev.keyCode == 8 || ev.keyCode == 46) && this.value.length == 1) || _PWH.selected) {
            this.value = '';
            this.blur();
            this.focus();
            _PWH.selected = false;
          }
        });
        el.addEventListener("mousedown",function(ev){
            if(_PWH.touched){
                _PWH.touched=false;
                return;
            }
            this.type='text';
        });
        el.addEventListener("touchstart",function(ev){
            this.type='text';
            _PWH.touched = true;
            this.focus(); // ensures the keyboard popsup
        });
        el.addEventListener("focus",function(ev){
            this.type='password';
        });
      }
    }
    // Comment this out to disable
    _PWH.init();
  }
</script>

答案 10 :(得分:0)

我是通过将输入字段设置为“文本”,然后捕获并操纵输入键来实现的

首先激活捕获按键的功能

yourInputElement.addEventListener('keydown', onInputPassword);

onInputPassword函数是这样的: (假设您在某处定义了“密码”变量)

onInputPassword( event ) {
  let key = event.key;
  event.preventDefault(); // this is to prevent the key to reach the input field

  if( key == "Enter" ) {
    // here you put a call to the function that will do something with the password
  }
  else if( key == "Backspace" ) {
    if( password ) {
      // remove the last character if any
      yourInputElement.value = yourInputElement.value.slice(0, -1);
      password = password.slice(0, -1);
    }
  }
  else if( (key >= '0' && key <= '9') || (key >= 'A' && key <= 'Z') || (key >= 'a' && key <= 'z') ) {
    // show a fake '*' on input field and store the real password
    yourInputElement.value = yourInputElement.value + "*";
    password += key;
  }
}

因此所有字母数字键都将添加到密码中,“退格”键将删除一个字符,“输入”键将终止,其他所有键都将被忽略

别忘了在末尾的某个地方调用removeEventListener('keydown',onInputPassword)

答案 11 :(得分:0)

我将创建一个会话变量并将其随机化。然后根据会话变量构建id和name值。然后在登录时询问您创建的会话变量。

if (!isset($_SESSION['autoMaskPassword'])) {
    $bytes = random_bytes(16);
    $_SESSION['autoMask_password'] = bin2hex($bytes);
}

<input type="password" name="<?=$_SESSION['autoMaskPassword']?>" placeholder="password">

答案 12 :(得分:0)

这对我有用:

<form action='/login' class='login-form' autocomplete='off'>
  User:
  <input type='user' name='user-entry'>
  <input type='hidden' name='user'>

  Password:
  <input type='password' name='password-entry'>
  <input type='hidden' name='password'>
</form>

答案 13 :(得分:0)

< 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');
  });
}

答案 14 :(得分:0)

我阅读了所有答案,几乎准备好自己不做,因为我已经在这里看到了几个答案,但是后来我决定总结以上所有内容。

基于HTML语言和规则的简短答案是您不能做到。但这只是懒惰者使用的答案。任何具有中等技能的程序员都知道,创建软件意味着90%的时间都在框外思考。

编程语言就像木匠工具一样,它们并不决定最终结果,它们只是帮助木匠到达那里。

针对我们的问题,有两种解决方案:纯HTML和Javascript。首先,您必须了解浏览器如何确定您所拥有的输入类型。它总是在寻找文本和密码,电子邮件和密码,在极少数情况下是电话和密码。

正如Gaurav Singh回答的那样,纯HTML解决方案是在密码上方放置一个虚拟(隐藏)输入字段,浏览器将尝试将其与密码字段配对。某些浏览器已经知道这种解决方法,因此,隐藏字段不再起作用。在这种情况下,您只需添加一些CSS规则即可将虚拟输入放置在屏幕外部,并将其大小设置为0 px。

使用Javascript解决方案在文档加载后生成字段并将其显示给用户,以防浏览器不再关注。它的完成方式实际上取决于您想要(真正地)需要多少安全性以及代码的跟踪量(以防万一您不知道可以完全跟踪JS代码)。 >

以后的编辑:我忘了提一下,为了工作,您不能在表单内使用经典的提交,您必须通过JS,AJAX或其他方式发送值,但是同样可以对其进行跟踪。

就个人而言,我喜欢使用虚拟输入,只是因为没有安全性问题。顺便说一句,保护登录页面是一项简单的任务,只有“专家”认为并非如此,这会使它变得复杂。登录过程唯一真正的问题是处理脚本的安全性,以确保用户不会尝试在此处注入内容。除此之外,什么都没有。

希望有帮助!

甚至以后进行编辑:

抱歉,对于HTML解决方案,我忘了提及这一点。您至少需要输入2-3个虚拟密码,否则浏览器只会选择实际的一个。在我看来,浏览器正在尽力而为地选择您的数据。...有点奇怪。

答案 15 :(得分:0)

几年前我需要这个特定情况:两个知道他们的网络密码的人同时访问同一台机器以签署法律协议。您不希望在这种情况下保存任何密码,因为保存密码是一个法律问题,而不是技术问题,其中两个人的身体和时间存在都是强制性的。现在,我同意这是一种罕见的情况,但是这种情况确实存在,并且Web浏览器中的内置密码管理器是无益的。

上面的技术解决方案是在passwordtext类型之间进行切换,并在字段为纯文本字段时使背景颜色与文本颜色匹配(从而继续隐藏密码)。浏览器不会要求保存存储在纯文本字段中的密码。

jQuery插件:

https://github.com/cubiclesoft/php-flexforms-modules/blob/master/password-manager/jquery.stoppasswordmanager.js

以上链接的相关源代码:

(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

单击菜单中的“添加条目”,然后滚动到页面底部的“模块:停止密码管理器”。

答案 16 :(得分:0)

您可以做的一件事是要求您的用户停用保存您网站的密码。这可以在浏览器范围内或原始范围内完成。

有些东西,否则你可以做的是在页面加载后(以及浏览器自动完成字段后)强制输入为空。将此脚本放在<body>元素的末尾。

userIdInputElement.value = "";
userPasswordInputElement.value = "";

答案 17 :(得分:0)

一种方法是生成随机输入名称并使用它们。

这样,浏览器每次都会显示new表单,并且无法预先填充输入字段。 如果您向我们提供一些示例代码(您是否有js spa应用程序或某些服务器端呈现),我很乐意帮助您实施。

此致

答案 18 :(得分:0)

试试这可能对您有所帮助,有关详细信息,请访问Input type=password, don't let browser remember the password

&#13;
&#13;
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();
    })
&#13;
<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">
&#13;
&#13;
&#13;

答案 19 :(得分:0)

虽然上面给出的解决方案非常正确,但如果您绝对需要该功能,那么您可以使用text-field和javascript来模拟自定义输入的情况。

为了安全使用,您可以使用任何加密技术。因此,这样您就可以绕过浏览器的密码保存行为。

如果您想了解更多有关这个想法的信息,我们可以在聊天中讨论这个问题。但是上面讨论了要点,你可以得到这个想法。

答案 20 :(得分:0)

我认为在最新的浏览器中是不可能的。 只有这样你可以使用另一个隐藏的密码字段并在从可见密码字段中获取值后将其用于逻辑,同时提交并将虚拟字符串放入可见密码字段中。 在这种情况下,浏览器可以存储虚拟字符串而不是实际密码。

答案 21 :(得分:-1)

密码字段工作正常,可以防止记住其历史记录

$('#multi_user_timeout_pin').on('input keydown', function(e) {
  if (e.keyCode == 8 && $(this).val().length == 1) {
    $(this).attr('type', 'text');
    $(this).val('');
  } else {
    if ($(this).val() !== '') {
      $(this).attr('type', 'password');
    } else {
      $(this).attr('type', 'text');
    }
  }

});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" id="multi_user_timeout_pin" name="multi_user_pin" autocomplete="off" class="form-control" placeholder="Type your PIN here" ng-model="logutUserPin">

答案 22 :(得分:-1)

在这种情况下,我会在内部JavaScript代码检索原始密码之后,但在提交表单之前,在密码字段中填充一些随机字符。

注意:表单肯定会将实际密码用于下一步。该值首先传输到隐藏字段。请参见代码示例。

这样,当浏览器的密码管理器保存密码时,它实际上并不是用户在那里输入的密码。因此,用户认为密码已保存,实际上是保存了一些随机的东西。随着时间的流逝,用户会知道他/她不能信任密码管理器来为该站点执行正确的工作。

现在,这可能会导致不良的用户体验;我知道,因为用户可能会觉得浏览器确实保存了密码。但是只要有足够的文档,就可以对用户进行管理。我认为这是一种可以完全确保用户输入的实际密码不会被浏览器获取并保存的方式。

<form id='frm' action="https://google.com">
    Password: <input type="password" id="pwd" />
    <input type='hidden' id='hiddenpwd' />
    <button onclick='subm()'>Submit this</button>
</form>

<script>
    function subm() {
        var actualpwd = $('#pwd').val();
        $('#hiddenpwd').val(actualpwd);
        // ...Do whatever Ajax, etc. with this actual pwd
        // ...Or assign the value to another hidden field
        $('#pwd').val('globbedygook');
        $('#frm').submit();
    }
</script>

答案 23 :(得分:-1)

在点击事件之前,我只是将字段密码的type属性更改为hidden:

document.getElementById("password").setAttribute("type", "hidden");
document.getElementById("save").click();

答案 24 :(得分:-1)

密码输入框本质上是字符替换。 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: &#34;htmlpassword&#34;;">

答案 25 :(得分:-7)

您可以通过转到设置/密码和表单&gt;在Google Chrome中执行此操作禁用[启用自动填充功能,只需点击一下即可填写网络表单。]并禁用[通过Google智能锁密码保存密码。]