1

我正在尝试在 PHP 中编写一个验证以下内容的正则表达式:

  • 至少 10 个字符
  • 至少有 2 个大写字符
  • 至少有 2 个数字或符号

我几乎查看了我能找到的所有参考资料,但无济于事。

我想我可以单独测试,但这让我很伤心:(

有人可以帮忙吗?(然后把我送到一个我可以用简单的英语 Reg Ex 学习的地方?)

4

3 回答 3

8

这张图值1000多字

(这是很多熵)

密码短语和熵

(图片来自 XKCD)

考虑到这一点,如果密码长度高于 X(例如.. 20),您可能需要考虑删除规则 2 和 3,或者将最小值增加到至少 16 个字符(作为唯一规则)。


至于你的要求:

与拥有一个庞大、丑陋、难以维护的高级正则表达式相反,您可能希望将问题分解为较小的部分,并使用专用函数分别处理每一位。

为此,您可以查看ctype_*函数count_chars()多字节字符串函数


现在丑了:

此高级 RegEx 将返回truefalse根据您的规则:

preg_match('/^(?=.{10,}$)(?=.*?[A-Z].*?[A-Z])(?=.*?([\x20-\x40\x5b-\x60\x7b-\x7e\x80-\xbf]).*?(?1).*?$).*$/',$string);

在这里测试演示:http ://regex101.com/r/qE9eB2

第一部分(LookAhead):(?=.{10,}$)将检查字符串长度,如果它至少有 10 个字符,则继续。您可以放弃它并使用strlen()甚至更好的 mb_strlen()进行检查。

第二部分(也是 LookAhead):(?=.*?[A-Z].*?[A-Z])将检查是否存在 2 个大写字符。您也可以$upper=preg_replace('/[^A-Z]/','',$string)改为 a 并将字符数计为$upper两个以上。

3rd LookAhead 使用一个字符类:[\x20-\x40\x5b-\x60\x7b-\x7e\x80-\xbf]为常见符号使用十六进制转义字符范围(几乎可以在普通键盘上找到所有符号)。您也可以$sym=preg_replace('/[^a-zA-Z]/','',$string)改为 a 并将字符数计为$sym两个以上。注意:为了缩短我使用递归组(?1)不再重复相同的字符类

对于学习,我所知道的最全面的 RegExp 参考是:regular-expressions.info

于 2013-04-02T00:26:15.783 回答
1

您可以使用前瞻来确保正确包含您要查找的内容。

/(?=.*[A-Z].*[A-Z])(?=.*[^a-zA-Z].*[^a-zA-Z]).{10,}/
于 2013-04-01T22:54:20.810 回答
1

我一直喜欢用好的旧程序代码来处理这样的事情。正则表达式可能很有用,但它们也可能有点麻烦,特别是对于代码维护和快速扫描(正则表达式并不完全是可读性的例子)。

function strContains($string, $contains, $n = 1, $exact = false) {
    $length = strlen($string);
    $tally  = 0;
    for ($i = 0; $i < $length; $i++) {
        if (strpos($contains, $string[$i]) !== false) {
            $tally++;
        }
    }
    return ($exact ? $tally == $n : $tally >= $n);
}
function validPassword($password) {
    if (strlen($password) < 10) {
        return false;
    }
    $upperChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $upperCount = 2;
    if (strContains($password, $upperChars, $upperCount) === false) {
        return false;
    }
    $numSymChars = '0123456789!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~';
    $numSymCount = 2;
    if (strContains($password, $numSymChars, $numSymCount) === false) {
        return false;
    }
    return true;
}
于 2013-04-02T01:11:26.223 回答