【问题标题】:How to prevent a browser from storing passwords如何防止浏览器存储密码
【发布时间】:2017-05-04 04:13:25
【问题描述】:

我需要阻止浏览器存储用户名和密码值,因为我正在开发一个包含更安全数据的 Web 应用程序。我的客户要求我这样做。

我在 HTML 表单和密码字段中尝试了 autocomplete="off" 属性。但它不适用于 Chrome 55、Firefox 38+、Internet Explorer 11 等最新浏览器。

什么是最好的解决方案?

【问题讨论】:

  • 我有类似的情况 - 一个内部 Web 应用程序,它有一个仅限技术支持的区域,其中密码解锁了应用程序的不安全功能。允许最终用户访问这将是非常糟糕的,所以是的,在某些情况下您不希望保存密码。顺便说一句,仍在寻找有效的答案。
  • 一个用例是用户共享一台计算机,但需要以个人身份登录到 web 应用程序。
  • 我的解决方案有点hack,但是我用JS清场了。
  • 我真的不建议人们在 2020 年这样做,除非你有非常特殊的情况。这使安全性变得更糟。用户应该为他们使用的每项不同服务使用唯一的密码。当然,没有办法记住这么多唯一且不相关的密码,因此用户需要使用密码管理器来做到这一点。所有大型浏览器都有内置的,并且有很多 3rd 方选项。除了一些特殊情况例外,阻止密码管理器最终可能会损害您的安全而不是帮助它。
  • @Chris - 这正是“特殊情况例外”为什么真的应该有一种正确的方法来做到这一点。在极少数情况下,重点是确认用户仍然是同一用户,或者当他们更改密码并且您(作为开发人员)知道保存的值一定是错误的时。

标签: html security browser


【解决方案1】:

感谢您给我答复。我点击了以下链接

Disable browser 'Save Password' functionality

我通过在输入中添加readonlyonfocus="this.removeAttribute('readonly');" 属性解决了这个问题,如下所示。

<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 属性不再被浏览器支持
  • 试过了,也不管用 esp firefox dev edition
  • 我的解决方案有点hack,但是我用JS清场了。
  • 在我的登录页面(mvc 项目)上我添加了:onfocus ="this.removeAttribute('readonly');", onfocusout ="this.setAttribute('readonly','readonly');"它就像一个魅力!即使在 FireFox ‏67.0.4 ‏(64 bits) 中!谢谢!
  • 在 firefox 浏览器版本 84.0b8(64 位)中不起作用。
【解决方案2】:

不建议尝试阻止浏览器存储密码。 一些变通方法可以做到这一点,但现代浏览器不提供开箱即用的此功能,这是有充分理由的。现代浏览器将密码存储在密码管理器中,以使用户能够使用比平时更强的密码。

正如MDN: How to Turn Off Form Autocompletion所解释的:

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

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

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

因此,许多现代浏览器不支持 autocomplete="off" 登录字段:

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

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

这是 Firefox(自 38 版起)、Google Chrome(34 版起)和 Internet Explorer(11 版起)中的行为。

如果作者想防止在用户管理页面中自动填充密码字段,用户可以为自己以外的人指定新密码,则应指定autocomplete="new-password",尽管尚未完全实现对此的支持浏览器。

【讨论】:

  • 在浏览器中显示密码是如此简单。只需打开开发人员工具,将输入类型从密码更改为文本,瞧!就是这样。
  • 在某些用例中密码管理器毫无意义。比如修改密码。 autocomplete="new-password" 在 Firefox 55.0.3 x64 上对我不起作用
  • 谢谢,为我工作,这很简单。我使用的是 Chome 版本 64.0.3282.186 (Official Build) (64-bit)
  • 在 Chrome 65 中,autocomplete="new-password" 与我想要的完全相反。它没有显示“您要更新保存的密码...”对话框...它只是默默地更新我存储的密码。比无用更糟糕 - 危险! >:(
  • 当您在开发和支持设置密码字段的管理界面时,强制执行这是否是一件好事的语义完全没有意义!您认为强制浏览器让管理员为他们在浏览器中创建的每个用户保存每个密码是否更安全!?!每次我读到那个“净收益”的评论,我都会在内心深处死去。
【解决方案3】:

这是一个纯 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;">

据我测试,此解决方案适用于 ChromeFirefox 59.0(64 位)Internet Explorer 11.0.9600 > 以及 IE Emulators Internet Explorer 5 及更高版本。

【讨论】:

  • 这可能是个坏主意,因为密码字段有一些额外的安全属性——例如。无法复制粘贴其中的文本。
  • @tXK 我同意没有你.. 但你可以通过快速技巧复制/粘贴密码字段内的文本,例如在 chrome 中,右键单击密码字段,转到检查然后更改类型="password" 到 type="text"。
  • 复制/粘贴不应被视为密码字段中的问题,因为这是密码管理器的理论基础。问特洛伊亨特。
  • 我认为这不是一个好主意。例如如果我们有自动文件管理器或密码管理器扩展它如何识别密码字段,可能有一些选项可以找到它..但这对初学者来说不是一个好课
  • 这是在 React with Chrome 上真正对我有用的唯一解决方案。
【解决方案4】:

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

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

【讨论】:

  • 奇怪,mdn 建议 new-password,但在 FF 中对我都不起作用。
【解决方案5】:

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

<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>

【讨论】:

  • 天才! :) 我会给它一个值,比如 value="x"。而且我不会使用 display:none,而是使用窗口外的荒谬位置,或负 z-index。
  • 怎么样?
  • 在浏览器 firefox 84.0b5 (64-bit) 版本中不起作用。
【解决方案6】:

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

要实现这一点,请在实际输入之前添加一个 虚拟输入,并使用 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>

【讨论】:

    【解决方案7】:

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

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

    【讨论】:

    • 请注意,许多浏览器不支持此功能。这些只会以明文形式显示输入的密码。
    【解决方案8】:

    在发布此内容时,以前的答案都不适用于我。

    此方法使用可见密码字段从用户那里获取密码,并使用隐藏密码字段将密码传递给服务器。在提交表单之前,可见密码字段是空白的,但不会在表单submit 事件处理程序中(参见下一段的解释)。这种方法尽快将可见密码字段值传输到隐藏密码字段(没有不必要的开销),然后清除可见密码字段。如果用户返回可见密码字段,则恢复该值。它使用占位符在字段被清除后显示●●●。

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

    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"/>

    【讨论】:

      【解决方案9】:
      < 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');
        });
      }
      

      【讨论】:

      • 解释一下。
      【解决方案10】:

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

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

      对于输入(在我的例子中是 MUI TextField),我将 type 设置为 "text" 而不是 "password",以便绕过 Chrome 检测存储凭证功能。我将 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)
      

      }

      【讨论】:

        【解决方案11】:

        这对我有用:

        <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>
        

        【讨论】:

        • 注意:并非所有浏览器都支持自动完成属性!
        【解决方案12】:

        我认为在最新的浏览器中是不可能的。

        您可以做到这一点的唯一方法是获取另一个隐藏密码字段并将其用于您的逻辑,然后从可见密码字段中获取值,同时提交并将虚拟字符串放入可见密码字段中。

        在这种情况下,浏览器可以存储一个虚拟字符串而不是实际密码。

        【讨论】:

          【解决方案13】:

          虽然之前的解决方案非常正确,但如果您绝对需要该功能,那么您可以使用文本字段和 JavaScript 通过自定义输入来模拟这种情况。

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

          如果您想了解更多关于这个想法的信息,我们可以在聊天中讨论。但是在以前的答案中讨论了要点,您可以理解。

          【讨论】:

            【解决方案14】:

            试试下面的。可能对你有帮助。

            欲了解更多信息,请访问Input type=password, don't let browser remember the password

            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">

            【讨论】:

              【解决方案15】:

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

              这样,浏览器每次都会显示new 表单,并且无法预填充输入字段。

              如果您向我们提供一些示例代码(您是否有 JavaScript single-page application (SPA) 应用程序或一些服务器端渲染),我很乐意在实施过程中为您提供帮助。

              【讨论】:

              • 这不起作用 - 即使该字段没有名称或 ID,密码管理器也会提示(无论如何在 Firefox 上)
              【解决方案16】:

              几年前我需要这个来解决一个特定的情况:两个知道自己网络密码的人同时访问同一台机器以签署法律协议。

              您不希望在这种情况下保存任何一个密码,因为保存密码是一个法律问题,而不是一个技术问题,即两个人的物理和时间都必须存在。现在,我同意这是一种罕见的情况,但这种情况确实存在,并且网络浏览器中的内置密码管理器无济于事。

              我对上述问题的技术解决方案是在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

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

              【讨论】:

              • 对于该演示 Chrome 要求保存密码版本 65.0.3325.146
              • 已确认。 Chrome 63 似乎没有这种行为。看起来在 Chrome 64 中按下 Enter 键会在调用元素上的模糊处理程序之前提交表单,因此 Chrome 会看到密码字段。但是,如果您先单击元素外部然后提交,Chrome 不会抱怨。对我来说,这似乎是 Chrome 中的一个错误:提交表单应始终在提交之前调用焦点元素上的所有相关事件处理程序,因为可能需要运行的验证代码会阻止表单提交。 Firefox 和 Edge 都在这里做正确的事。
              • 上述错误和我遇到的另一个错误已修复。
              • 该修复程序的工作原理是它隐藏了弹出窗口,但是,仍然有一种方法可以查看密码。用户可以单击 chrome URL 栏中的“钥匙”图标,如果他们知道操作系统的帐户密码,则可以在任何密码文本输入中查看最后输入的已知密码。据我所知,表格甚至不必提交。在提交之前刷新页面现在还不够。所以我的理论是现在必须直接将击键记录到任何输入类型=密码中,而不是事后读取 dom 元素。
              • 所以 Chrome 自带了自己的密码 DOM logger。极好的。这正是每个人都需要的。 Broken-by-design Web 浏览器功能已损坏。 Firefox 和 Edge 没有这个问题。除了希望 Google 放弃该非功能之外,无能为力,当然,除非有人想发疯并完全用 Javascript 模拟密码字段。
              【解决方案17】:

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

              您可以做的其他事情是在页面加载后(以及在浏览器自动完成字段后)强制输入为空。将此脚本放在&lt;body&gt; 元素的末尾。

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

              【讨论】:

                【解决方案18】:

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

                if (!isset($_SESSION['autoMaskPassword'])) {
                    $bytes = random_bytes(16);
                    $_SESSION['autoMask_password'] = bin2hex($bytes);
                }
                
                <input type="password" name="<?=$_SESSION['autoMaskPassword']?>" placeholder="password">
                

                【讨论】:

                  【解决方案19】:

                  我通过将输入字段设置为“文本”,并捕获和操作输入键来做到这一点

                  首先激活一个函数来捕捉键

                  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)

                  【讨论】:

                    【解决方案20】:

                    这里是纯html/css(无js)解决方案

                    <textarea required="required" autocorrect="off" autocapitalize="off" name="username" class="form-control" placeholder="Your username"  rows="1" cols="20" wrap="off"></textarea>
                    <textarea required="required" autocorrect="off" autocapitalize="off" name="password" class="form-control password" placeholder="Your password"  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';
                    }
                    

                    注意事项

                    1. Textarea 阻止自动填充和密码管理器触发
                    2. wrap=off/overlow=hidden/rows=1 强制单行显示
                    3. 所需的伪 css 使占位符有效
                    4. 您可能需要一些“防止 eventKey=13 / 提交”的东西
                    5. 在 ffox/chrome/iOS 下运行良好

                    最后,它最终变成了一堆骇人听闻的黑客攻击(但它确实有效)

                    【讨论】:

                    • 这有一个问题,现在浏览器+操作系统不知道该字段应该被视为安全密码输入。因此,它可以被任何具有粘贴板访问权限的东西复制粘贴和读取,它可以更容易地被键盘监控程序读取,因为它不被视为安全输入,或者任何具有屏幕阅读器/可访问性访问权限的东西都可以读取它,等等。实际密码字段具有许多理想的安全属性。
                    【解决方案21】:

                    密码字段可以很好地防止记住其历史记录:

                    $('#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】:

                      在这种情况下,我在内部 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>
                      

                      【讨论】:

                      • @AristeidisKaravas 网络上的几个银行应用程序,使用这种方法来确保永远不会存储实际密码——他们用任意字符填充密码字段只是为了混淆浏览器密码管理器
                      【解决方案23】:

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

                      【讨论】:

                        【解决方案24】:

                        我只是在点击事件前将字段密码的type属性改为隐藏:

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

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 2023-03-18
                          • 1970-01-01
                          • 2020-06-07
                          • 1970-01-01
                          • 2015-10-05
                          • 1970-01-01
                          • 2023-03-21
                          • 1970-01-01
                          相关资源
                          最近更新 更多