正则表达式特定的密码限制

时间:2016-09-26 18:30:09

标签: c++ regex

我需要验证密码才能满足这些规则的至少三种组合:
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-z\d]+)(?=.*[A-z@!?]+)(?=.*[a-z\d@!?]+)(?=.*[A-Z\d@!?]+)[A-z\d@!?]{8,}

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

2 个答案:

答案 0 :(得分:1)

显而易见,你的问题有点困难。所以我会把它分成更容易理解的部分。这将有助于这么多。看看我做的这个例子:

#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 . . .\n\n";
        }
        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 . . .\n\n";
            }
            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!

正如您所看到的,这种方式更好,更容易理解。我希望能帮到你!

答案 1 :(得分:1)

让我们解决这个问题,password strength checkers like this do not work

  

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

这是关于这个主题的Sophos:"Why you can’t trust password strength meters""Why you STILL can’t trust password strength meters"

  

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

     

这有助于确定密码抵御暴力攻击的能力(攻击者随机猜测),但是只有攻击者会做的事情才能抵御暴力攻击才有用,而且可能不是

这是Concordia大学,"From Very Weak to Very Strong: Analyzing Password-Strength Meters"

  

在我们的大规模实证分析中,很明显   通常使用的仪表高度不一致,失败   提供有关用户选择的一致反馈,有时也是如此   提供明显具有误导性的强度测量。

多年来密码数据库的所有细节都让攻击者多年来研究数以亿计的真实密码并寻找可利用的模式。 P4ssw0rd!不再适用了,他们正在接受我们的伎俩。他们知道将a替换为4。他们知道在最后坚持一个标点字符。他们知道上部套管字典单词的第一个字母。攻击者使用低成本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]/
  5. 哦,等等...... Unicode。您必须使用POSIX character classes否则您将拒绝Élan1;。这些是Perl的工作方式,您的语言可能会有所不同。

    1. /[[:upper:]]/
    2. /[[:lower:]]/
    3. /[[:digit:]]/
    4. /[^[:alnum:]]/
    5. 这很容易做错,并使用户烦恼。做正确的事情有点工作。它没有添加任何安全性。这就是为什么我建议不要打扰。