【问题标题】:How to do a strong validation of password entry and validate confirm password entry如何对密码输入进行强验证并验证确认密码输入
【发布时间】:2019-12-09 04:07:10
【问题描述】:

我有一些 HTML 和 Javascript 要求用户使用以下规则输入密码:

  1. 至少 8 个字符
  2. 至少 1 个大写字母
  3. 至少 1 个小写字母
  4. 至少 1 个特殊字符
  5. 至少 1 个数字字符

这之后是密码确认条目。在密码和密码确认输入下方有 div 块,其中包含包含在 p 标记中的错误消息,这些错误消息应该在发生任何错误时变得可见。它似乎不起作用。

我还在此 CSHTML 文件中使用 C# Razor 代码,因此我需要在字符串中使用“@@”而不是 @。如果我错了,请告诉我。

密码:(必须包含至少 1 个小写字母字符、1 个大写字母字符、1 个特殊字符、1 个数字字符和至少 8 个字符长)

        <input type="password" name="password_admin1_create" oninput="return validate_password()"><br><br>
        <script>
            var password = document.getElementsByName("password_admin1_create")[0];
            function validatePassword(val) {
                var strongRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@@#\$%\^&\*])(?=.{8,})/;
                console.log(re.test(val))
                return strongRegex.test(val);
            }

            function validate_password() {
                if (validatePassword(password.value)) {
                    document.getElementById("password_result_invalid").style.visibility = "hidden";
                    document.getElementById("password_result_invalid").style.height = "0";
                } else {
                    document.getElementById("password_result_invalid").style.visibility = "visible";
                    document.getElementById("password_result_invalid").style.height = "initial";
                }
            }
        </script>
        <div id="password_result_invalid" class="error_verify">
            <p style="color:red">Invalid password format.</p>
        </div>

        <p>Please confirm the password:</p>
        <input type="password" name="password_admin1_create_confirm" oninput="return validate_password_confirm()"><br><br>
        <script>
            var password_confirm = document.getElementsByName("password_admin1_create_confirm")[0].value;
            var password = document.getElementsByName("password_admin1_create")[0].value;

            function validate_password_confirm() {
                if (password_confirm == password) {
                    document.getElementById("password_confirmation_invalid").style.visibility = "hidden";
                    document.getElementById("password_confirmation_invalid").style.height = "0";
                } else {
                    document.getElementById("password_confirmation_invalid").style.visibility = "visible";
                    document.getElementById("password_confirmation_invalid").style.height = "initial";
                }
            }
        </script>
        <div id="password_confirmation_invalid" class="error_verify">
            <p style="color:red">Passwords do not match.</p>
        </div>

【问题讨论】:

  • 那么问题是什么?
  • 什么不适合你?附带说明一下,如果密码包含空格,最后一个断言 (?=.{8,}) 也会成功。
  • 错误消息在预期的时候是不可见的。我尝试输入一个不带空格的无效密码,但没有错误消息
  • 复杂的密码规则通常不会带来更安全的密码,重要的只是最小长度。人们无法记住大量的强密码,这样的规则会干扰好的密码方案。人们可以非常有创意地绕过这些规则,例如通过使用“Password-2019”等弱密码。通常,您最终会使用较弱的密码而不是较强的密码。最近 NIST 发布了official paper,建议反对此类规则,并反对其以前的建议。

标签: javascript regex passwords


【解决方案1】:

您一直看到Invalid password format. 的原因是您首先创建了一个变量:

var password = document.getElementsByName("password_admin1_create")[0];

稍后,您再次创建它,直接将其设置为值(为空

var password = document.getElementsByName("password_admin1_create")[0].value;

因此变量密码将始终保持为空,并且永远不会通过正则表达式检查。

注意

这个变量password_confirm也直接设置为空,在console.log(re.test(val))中没有re

关于模式

你可以对你的模式做一些小的调整:

  • 前瞻 (?=.{8,}) 断言右边的内容是任何字符的 8 倍以上,这也将匹配一个空格。
  • 您可以更新它以使用字符类仅匹配您允许匹配的字符,并使用锚点$ 来断言字符串的结尾。
  • 该模式可以使用contrast 来断言例如不是数字,然后是数字。

例如:

^(?=[^a-z]*[a-z])(?=[^A-Z]*[A-Z])(?=[^0-9]*[0-9])(?=[^!@#$%^&*]*[!@#$%^&*])(?=[!@#$%^&*A-Za-z0-9]{8,}$)

Regex demo

您更新后的代码可能如下所示:

<input type="password" name="password_admin1_create" oninput="validate_password()"><br><br>
<script>

    function validatePassword(password) {
        return /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*])(?=.{8,})/.test(password);
    }

    var password = document.getElementsByName("password_admin1_create")[0];

    function validate_password() {

        if (validatePassword(password.value)) {
            document.getElementById("password_result_invalid").style.visibility = "hidden";
            document.getElementById("password_result_invalid").style.height = "0";
        } else {
            document.getElementById("password_result_invalid").style.visibility = "visible";
            document.getElementById("password_result_invalid").style.height = "initial";
        }
    }
</script>
<div id="password_result_invalid" class="error_verify">
    <p style="color:red">Invalid password format.</p>
</div>

<p>Please confirm the password:</p>
<input type="password" name="password_admin1_create_confirm" oninput="return validate_password_confirm()"><br><br>
<script>
    var password_confirm = document.getElementsByName("password_admin1_create_confirm")[0];
    var password = document.getElementsByName("password_admin1_create")[0];

    function validate_password_confirm() {
        if (password.value === password_confirm.value) {
            document.getElementById("password_confirmation_invalid").style.visibility = "hidden";
            document.getElementById("password_confirmation_invalid").style.height = "0";
        } else {
            document.getElementById("password_confirmation_invalid").style.visibility = "visible";
            document.getElementById("password_confirmation_invalid").style.height = "initial";
        }
    }
</script>
<div id="password_confirmation_invalid" class="error_verify">
    <p style="color:red">Passwords do not match.</p>
</div>

【讨论】:

    【解决方案2】:

    我的猜测是这个表达式可能有效:

    ^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[?!%@#$%^&*])[A-Za-z0-9?!%@#$%^&*]{8,}$
    

    我们将添加开始和结束锚点,并删除其中一些转义。

    表达式在regex101.com 的右上方面板中进行了解释,如果您想探索/简化/修改它,在this link 中,您可以查看它如何与一些示例输入进行匹配,如果您愿意的话。

    const regex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[?!%@#$%^&*])[A-Za-z0-9?!%@#$%^&*]{8,}$/gm;
    const str = `Az0^AAAA
    Az0^AAA
    Az0^AAAAA`;
    let m;
    
    while ((m = regex.exec(str)) !== null) {
        // This is necessary to avoid infinite loops with zero-width matches
        if (m.index === regex.lastIndex) {
            regex.lastIndex++;
        }
        
        // The result can be accessed through the `m`-variable.
        m.forEach((match, groupIndex) => {
            console.log(`Found match, group ${groupIndex}: ${match}`);
        });
    }

    【讨论】:

    • 你能给我一个测试用例吗?我尝试了一些测试,但我不断收到错误消息,即使至少有 8 个字符、1 个大写字母、1 个小写字母、1 个数字和 1 个特殊字符。
    【解决方案3】:

    使用模式正则表达式:

    1. 至少 8 个字符
    2. 至少 1 个大写字母
    3. 至少 1 个小写字母
    4. 至少 1 个特殊字符
    5. 至少 1 个数字字符

    "^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&amp;])[A-Za-z\d@$!%*?&amp;]{8,}$"

    用法:

    <input type="password" name="pw" pattern="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$" title="Strong Password">
    

    【讨论】:

      【解决方案4】:

      这是我几周前做的。只是发布它,看看它是否可以帮助你(我知道它不是最干净的)

      HTML

      所有要求如上所示,最初为红色。

      <div class="requirements">
          <ul>
              <li id="length" class="red">Include at least 8 digits and three special characters</li>
              <li id="uppercase" class="red">Include at least one upper case characters (A-Z)</li>
              <li id="lowercase" class="red">Include at least one lower case character (a-z)</li>
              <li id="numbers" class="red">Include a number (0-9)</li>
              <li id="symbols" class="red">Include a symbol (!, #, $, etc.)</li>
          </ul>
      </div>
      

      JS

      在当前页面的输入字段中添加按键事件处理程序:

      var inputfields = document.forms["changePasswordForm"].getElementsByTagName("input");
      for (var i = 0; i < inputfields.length; i++){
          inputfields[i].addEventListener('keyup', function(e){
              // On every key up, check the password
              var password = document.getElementById('sf_guard_user_password');
              validatePassword(password.value);
          })
      }
      

      最后我的(丑陋的)验证密码功能

      function validatePassword(password) {
      
                      // Minimum 8 characters
                      if (password.length > 7) {
                          document.getElementById('length').classList.remove('red');
                          document.getElementById('length').classList.add('green');
                      } else {
                          document.getElementById('length').classList.remove('green');
                          document.getElementById('length').classList.add('red');
                      }
      
                      // At least one uppercase
                      if (/[A-Z]/.test(password)) {
                          document.getElementById('uppercase').classList.remove('red');
                          document.getElementById('uppercase').classList.add('green');
                      } else {
                          document.getElementById('uppercase').classList.remove('green');
                          document.getElementById('uppercase').classList.add('red');
                      }
      
                      // At least one lowercase
                      if (/[a-z]/.test(password)) {
                          document.getElementById('lowercase').classList.remove('red');
                          document.getElementById('lowercase').classList.add('green');
                      } else {
                          document.getElementById('lowercase').classList.remove('green');
                          document.getElementById('lowercase').classList.add('red');
                      }
      
                      // At least one number
                      if (/[0-9]/.test(password)) {
                          document.getElementById('numbers').classList.remove('red');
                          document.getElementById('numbers').classList.add('green');
                      } else {
                          document.getElementById('numbers').classList.remove('green');
                          document.getElementById('numbers').classList.add('red');
                      }
      
                      // At least one symbol
                      if (/[$@$!%*#?&]/.test(password)) {
                          document.getElementById('symbols').classList.remove('red');
                          document.getElementById('symbols').classList.add('green');
                      } else {
                          document.getElementById('symbols').classList.remove('green');
                          document.getElementById('symbols').classList.add('red');
                      }
      
                  }
      

      最后,如果满足所有要求,我会检查提交:

      document.getElementById('changePasswordForm').addEventListener('submit',  function(e){
          e.preventDefault();
          // Once again ugly because length is fixed
          if (document.getElementsByClassName('green').length > 4) {
              document.getElementById('changePasswordForm').submit();
          }
      })
      

      我不知道这是否会对您有所帮助。但我试过了:)

      【讨论】:

        【解决方案5】:

        您应该将“模式”属性分配给任何符合您的密码要求的正则表达式。例如:

        <  input type="password" id="psw" name="psw" 
        pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}" 
        title="Must contain at least one number and one uppercase and lowercase letter, and at least 8 or more characters" 
        required >
        

        此链接也可能有帮助:https://www.w3schools.com/howto/howto_js_password_validation.asp

        【讨论】:

          猜你喜欢
          • 2020-11-24
          • 2015-04-03
          • 2023-02-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-09-18
          • 1970-01-01
          相关资源
          最近更新 更多