Regex特定的密码限制

Regex specific password restrictions

本文关键字:密码 Regex      更新时间:2023-10-16

我需要验证密码以满足以下规则的至少三种组合:
Upper case, lower case, number, special char
密码还需要至少8个字符长。

编辑
我知道这些密码限制是有创意的,这是一个请求,而不是我天真地想获得更强的密码

有效密码示例:

Password3   // Upper case, lower case, number
Password!   // Upper case, lower case, special
password3!  // Lower case, number, special
PASSWORD3!  // Upper case, number, special
Password3!  // Upper case, lower case, number, special

无效密码示例:

password    // Only lower case
password3   // Only lower case and number
password!   // Only lower case and special
Password    // Only Upper case and lower case
Pw3!        // Too short

这是我写的一个正则表达式:

(?=.*[A-zd]+)(?=.*[A-z@!?]+)(?=.*[a-zd@!?]+)(?=.*[A-Zd@!?]+)[A-zd@!?]{8,}

希望如此,我知道为什么这个正则表达式也匹配无效密码,如果是这样,我怎么能说表达式必须包含组中的所有内容,而不仅仅是一个匹配?

很明显,您的问题有点棘手。所以我会把它分成更容易理解的部分。这将大大帮助。看看我做的这个例子:

#include <iostream>
#include <string>
#include <regex>
int main(){
    bool upper_case = false; //saves the result if upper-case characters were found.
    bool lower_case = false; //same for lower-case
    bool number_case = false; //...
    bool special_char = false;

    std::regex upper_case_expression{ "[A-Z]+" }; //here is the very simple expression for upper_case search
    std::regex lower_case_expression{ "[a-z]+" }; //for lower-case
    std::regex number_expression{ "[0-9]+" }; //...
    std::regex special_char_expression{ "[@!?]+"};

    std::string pw;

    bool done = false; //let's assume we're not done
    do{ //do ask-for-password as long were not done
        std::cout << "Type in a valid password: ";
        std::getline(std::cin, pw); //get input
        if (pw.length() <= 8){ //too short!
            std::cout << "Invalid password! Try again . . .nn";
        }
        else{
            upper_case = std::regex_search(pw, upper_case_expression); //save the result, if the expression was found.
            lower_case = std::regex_search(pw, lower_case_expression); //....
            number_case = std::regex_search(pw, number_expression);
            special_char = std::regex_search(pw, special_char_expression);
            //like: sum_of_positive_results = 1 + 0 + 1 + 1 (true/false as an integer)
            int sum_of_positive_results = upper_case + lower_case + number_case + special_char; 
            if (sum_of_positive_results < 3){ //not enough booleans were true!
                std::cout << "Invalid password! Try again . . .nn";
            }
            else{ //otherwise it's valid!
                std::cout << "That's a valid Password!" << std::endl;
                done = true;
            }
        }
    } while (!done);
    return 0;
}

输出:

Type in a valid password: password
Invalid password! Try again . . .
Type in a valid password: Password
Invalid password! Try again . . .
Type in a valid password: password!
Invalid password! Try again . . .
Type in a valid password: password3
Invalid password! Try again . . .
Type in a valid password: not valid!
Invalid password! Try again . . .
Type in a valid password: Password!
That's a valid Password!

正如你所看到的,这是更好的,更容易遵循。我希望这对你有帮助!

让我们解决这个问题,像这样的密码强度检查器不起作用。

理论上,密码强度检查器不起作用。这是因为密码的强度不取决于密码值(你给检查器的(,而是取决于密码生成过程(你不经常正式化,更不用说在检查器中输入了(。

下面是Sophos的主题:;为什么你不能信任密码强度计"以及";为什么你仍然不能信任密码强度计"。

简单的密码表可以检查密码的长度和熵,并有建议用户在密码中包含的内容的清单;例如,大小写字母、数字和特殊字符的混合体。

这有助于确定密码抵御暴力攻击(攻击者随机猜测(的能力,但只有当攻击者打算这样做时,抵抗暴力攻击才有用,而且可能不是。

康考迪亚大学;从非常弱到非常强:分析密码强度计";。

在我们的大规模实证分析中常用的仪表高度不一致、故障为用户选择提供连贯的反馈,有时提供明显具有误导性的强度测量。

多年来,密码数据库的所有漏洞都让攻击者花了数年时间研究数亿个真实密码,并寻找可利用的模式。P4ssw0rd!不会再工作了,他们在耍我们的把戏。他们知道用4代替a。他们知道在末尾加一个标点符号。他们知道字典里单词的第一个字母是大写字母。攻击者使用低成本的GPU作为小型超级计算机来进行极端的并行处理,以尝试所有这些技巧。

更重要的是测量密码熵,基本上是将密码与现有模式匹配的难度。它看起来有多随意?人类真的不善于创造熵。编写一个熵检查器超出了这个答案的范围。

创建安全密码的唯一方法是使用最大可用长度为每个帐户随机生成一个新密码 ,并将其存储在密码库中任何涉及在脑海中编密码并记住密码的系统都已经被破坏

重点是:不要麻烦。马离开马厩很久之后,你就关上门了。

现在进入问题。


在多个正则表达式中执行

可以将其作为一个正则表达式来执行,但随后会出现无法读取、无法维护的混乱。如果你想添加,祝你好运。

另一个原因是很难从一次检查中找出密码失败的原因。没有什么比被告知密码无效更烦人的了,但不是为什么。一定要设计好你的密码检查功能,这样它就会显示哪个检查失败。

基本模式是编写一系列检查以使其失败。如果它通过了所有这些,它就通过了。这里有一个Perl的草图。

sub is_invalid_password {
    my $password = shift;
    # Instead of hard coding the wording of the message,
    # use constants. This lets the UX person handle the
    # wording. Also helps internationalization.
    return NEEDS_UPPER_CASE unless $password =~ /[A-Z]/;
    return NEEDS_LOWER_CASE unless $password =~ /[a-z]/;
    ...and so on...
    return 0;
}

它正在检查无效的密码,以便在失败时返回错误常量。这使得它的使用更加简单。只要确保所有的常量都是真值,你就可以写:

if( my $reason = is_invalid_password($password) ) {
    # Don't just say the password is invalid, say why.
    display_invalid_password_reason($reason);
}
else {
    store_password($password);
}

正则表达式是。。。

  1. /[A-Z]/
  2. /[a-z]/
  3. /[0-9]/
  4. /[^A-Za-z0-9]/

哦,等等。。。Unicode。您必须使用POSIX字符类,否则您将拒绝Élan1;。Perl就是这样做的,您的语言可能会有所不同。

  1. /[[:upper:]]/
  2. /[[:lower:]]/
  3. /[[:digit:]]/
  4. /[^[:alnum:]]/

这样做很容易出错并惹恼用户。要把它做好需要一点功夫。它没有增加任何安全性。这就是为什么我建议不要麻烦。