【问题标题】:Regex strong password the special characters正则表达式强密码特殊字符
【发布时间】:2017-02-26 10:17:50
【问题描述】:

我目前正在使用正则表达式进行一些测试。我有一个要求检查强密码的练习,这意味着它应该有:至少一个数字,一个小写字母,一个大写字母,没有空格,至少一个 不是字母或数字的字符。它应该在 8-16 个字符之间。

我写了这段代码:

     <?php

  $passwords = array("Jtuhn", "12J@k", "jok", "Joan 12@45", "Jghf2@45", "Joan=?j123j");

  foreach($passwords as $pass)
  {
    ///^\w*(?=\w*\d)(?=\w*[a-z])(?=\w*[A-Z])\w*$/
    if(strlen($pass) >= 8 && strlen($pass) < 17)
     {
       if(preg_match("/^\w*(?=\w*\d)(?=\w*[A-Z])(?=\w*[^0-9A-Za-z])(?=\w*[a-z])\w*$/", $pass) )
        echo "$pass => MATCH<br>";
       else
        echo "$pass => FAIL<br>";
     }
    else
      echo "$pass => FAIL(because of length)<br>";
  }
 ?>

最后两个应该匹配,但它们失败了。我认为问题在于

(?=\w*[^0-9A-Za-z])

这应该是模式匹配,至少有一个字符不是字母或数字,但我不知道为什么。 我知道这个强密码已在互联网上解决,但这不是我的问题。我的问题是为什么这部分工作没有做应该做的事情。

【问题讨论】:

  • 强密码是不可预测的密码,而正则表达式检查模式。如果某事遵循某种模式,则无法预测……此外,17 个字符的密码比 16 个字符的密码强,所以这是一个愚蠢的限制。
  • @Narf 好吧,我认为这没什么大不了的。我真正的问题是模式。假设 (?=\w*[^0-9A-Za-z]) 检查顺序无关紧要的特殊字符。但这不起作用。如果我删除它,如果密码包含一个大写字母、一个小写字母和一个数字,则模式可以很好地验证密码。当我添加那个时,它什么都不验证,都失败了。
  • 你的正则表达式是^\w*[lookaheads]\w*$。它不会匹配任何包含特殊字符的内容,并且它很容易发生灾难性的回溯。
  • @Rawing 为什么会这样?我应该从正则表达式中删除任何内容吗?
  • 只需在字符串开头触发前瞻断言。您的主要条件是匹配 8-16 个 非空格字符 ^\S{8,16}$ 并将您的条件添加到 ^ start like this

标签: php regex


【解决方案1】:

您可以将您的正则表达式拆分为不同的检查。

它将允许您编写更具可读性的条件并显示特定的错误消息。虽然,正则表达式模式更容易编写和理解。

即:

$errors = array();
if (strlen($pass) < 8 || strlen($pass) > 16) {
    $errors[] = "Password should be min 8 characters and max 16 characters";
}
if (!preg_match("/\d/", $pass)) {
    $errors[] = "Password should contain at least one digit";
}
if (!preg_match("/[A-Z]/", $pass)) {
    $errors[] = "Password should contain at least one Capital Letter";
}
if (!preg_match("/[a-z]/", $pass)) {
    $errors[] = "Password should contain at least one small Letter";
}
if (!preg_match("/\W/", $pass)) {
    $errors[] = "Password should contain at least one special character";
}
if (preg_match("/\s/", $pass)) {
    $errors[] = "Password should not contain any white space";
}

if ($errors) {
    foreach ($errors as $error) {
        echo $error . "\n";
    }
    die();
} else {
    echo "$pass => MATCH\n";
}

希望对您有所帮助。

【讨论】:

  • 是的,它有帮助。从每个字符串中找出哪些规则被破坏的好方法。谢谢
【解决方案2】:

你可以试试这个:

^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?!.* )(?=.*[^a-zA-Z0-9]).{8,16}$

它涵盖了您的所有要求

Explanation

  1. (?=.*\d)至少一个数字
  2. (?=.*[a-z])至少一个小写字母
  3. (?=.*[A-Z])至少一个大写字母
  4. (?!.* )没有空格
  5. (?=.*[^a-zA-Z0-9])a-zA-Z0-9 之外的至少一个字符
  6. .{8,16} 8 到 16 个字符

示例代码:

<?php
$re = '/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?!.* )(?=.*[^a-zA-Z0-9]).{8,16}$/m';
$str = 'Jtuhn
12J@k
jok
Joan 12@45
Jghf2@45
Joan=?j123j
';

preg_match_all($re, $str, $matches);
print_r($matches);

?>

Run it here

【讨论】:

  • 这很好,谢谢@Maverick_Mrt ^[a-zA-Z0-9] 意味着期待 a-zA-Z0-9。这个 [^a-zA-Z0-9] 错了吗?因为我在一本书中读到了这个,这就是我写它的原因......
  • @ Maverick_Mrt ,我复制粘贴你的正则表达式: ^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?!.* ) (?=.*^[a-zA-Z0-9]).{8,16}$ 效果很好我只是不明白,如果我想做的话 [^a-zA-Z0-9] 是错误的方法期待 a-zA-Z0-9 吗?
  • 很高兴它为你工作 [^A-Za-z0-9] 表示否定字符类它将匹配任何不是 A-Z 或 a-z 或 0-9 的东西......这是一个完全有效的语法
  • @JoanPlepi 删除了我的评论,因为我认为您的评论已经很清楚了 :) 我认为 ^[a-zA-Z0-9] 是一个错字。也许它起作用了,因为您尝试了多行模式。
  • 这很好,但是您应该取消无空格正则表达式并将密码长度限制提高到至少 100。密码应该被散列,这使得限制空格的需要无效,许多人使用密码管理器,它可以生成长达 100 个字符的密码。如果不考虑这一点,黑客就可以缩小密码选择范围,从而更有可能暴力破解帐户。
【解决方案3】:
^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}\S+$

//The rule is at least
   one upper case, one lower case, one digit[0-9], 
   one special character[#?!@$%^&*-] and the minimum length should be 8.

【讨论】:

    【解决方案4】:

    使用这个简单的正则表达式来测试一个强密码

    /(?=^.{8,}$)(?=.{0,}[A-Z])(?=.{0,}[a-z])(?=.{0,}\W)(?=.{0,}\d)/g
    

    Javascript:

    var password = "Abcdef@1234"
    var passwordRegex = /(?=^.{8,}$)(?=.{0,}[A-Z])(?=.{0,}[a-z])(?=.{0,}\W)(?=.{0,}\d)/g
    
    var isStrongPassword = passwordRegex.test(password)
    
    console.log(isStrongPassword, "<Strong password>")
    
    1. 最少 8 个字符
    2. 至少 1 个大写字母
    3. 至少 1 个小写字母
    4. 至少 1 个特殊字符
    5. 至少 1 位数字

    【讨论】:

      【解决方案5】:
      ^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[special characters]).{8,16}$
      

      根据需要添加特殊字符。

      以上代码检查以下条件

      • 至少 1 个大写字符
      • 至少 1 个小写字符
      • 至少 1 位数字
      • 至少 1 个特殊字符

      Click here to test

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-07-18
        • 1970-01-01
        • 2012-08-18
        • 2016-12-12
        • 2023-03-29
        • 2018-06-13
        • 2023-03-31
        • 1970-01-01
        相关资源
        最近更新 更多