关于c#:正则表达式,用于检查密码是否为“8个字符,包括1个大写字母,1个特殊字符,字母数字字符”

Regular expression to check if password is “8 characters including 1 uppercase letter, 1 special character, alphanumeric characters”

我想用正则表达式来检查

a password must be eight characters including one uppercase letter, one special character and alphanumeric characters.

这里是我的验证表达式,它适用于八个字符,包括一个大写字母、一个小写字母和一个数字或特殊字符。

1
2
(?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.
])(?=.*[A-Z])(?=.*[a-z]).*$"

如何为必须为八个字符(包括一个大写字母、一个特殊字符和字母数字字符)的密码编写它?


你所追求的正则表达式很可能是一个巨大的、需要维护的噩梦,特别是对于那些不太熟悉正则表达式的人来说。

我认为打破你的正则表达式,一次做一点会更容易。这可能需要更多的工作,但我很确定维护和调试它会更容易。这也将允许您向用户提供更多的定向错误消息(除了Invalid Password之外),这将改善用户体验。

从我所看到的情况来看,你对regex的理解相当流利,所以我假设给你正则表达式来做你需要做的事情是徒劳的。

看到你的评论,我会这样说:

  • 必须是八个字符长:您不需要regex。使用.Length属性就足够了。

  • 包括一个大写字母:可以使用[A-Z]+正则表达式。如果字符串至少包含一个大写字母,则此正则表达式将生成true

  • 一个特殊字符:您可以使用与非字母或数字的任何字符匹配的\W,或者使用类似的[!@#]来指定特殊字符的自定义列表。注意,虽然$^()等字符是正则表达式语言中的特殊字符,但它们需要像这样进行转义:\$。所以简而言之,您可以使用\W

  • 字母数字字符:使用\w+应匹配任何字母、数字和下划线。

查看本教程了解更多信息。


1
2
3
4
5
6
7
(                   # Start of group
    (?=.*\d)        #   must contain at least one digit
    (?=.*[A-Z])     #   must contain at least one uppercase character
    (?=.*\W)        #   must contain at least one special symbol
       .            #     match anything with previous condition checking
         {8,8}      #        length is exactly 8 characters
)                   # End of group

在一行中:

1
((?=.*\d)(?=.*[A-Z])(?=.*\W).{8,8})

编辑2019-05-28:

您需要匹配整个输入字符串。因此,可以将regex括在^$之间,以防止意外地假定部分匹配作为匹配的整个输入:

1
^((?=.*\d)(?=.*[A-Z])(?=.*\W).{8,8})$

资料来源:

  • 密码匹配表达式

  • 使用正则表达式验证密码强度


这么多答案……一切都糟透了!

正则表达式没有and运算符,因此很难编写一个与有效密码匹配的regex,当有效性由某物和其他某物以及其他某物定义时…

但是,正则表达式确实有一个或运算符,所以只需应用demorgan定理,并编写一个与无效密码匹配的regex。

任何少于8个字符或任何没有数字或任何没有大写字母或任何没有特殊字符的东西

所以:

1
^(.{0,7}|[^0-9]*|[^A-Z]*|[a-zA-Z0-9]*)$

如果有匹配的内容,那么它是一个无效的密码。


例如,如何使用可读/可维护的regex来实现这一点。

对于较长的regex,您应该始终使用RegexOptions.IgnorePatternWhitespace来允许表达式中的空白和注释,以提高可读性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
String[] passwords = {"foobar","Foobar","Foobar1","Fooobar12" };

foreach (String s in passwords) {

    Match password = Regex.Match(s, @"
                                      ^              # Match the start of the string
                                       (?=.*\p{Lu})  # Positive lookahead assertion, is true when there is an uppercase letter
                                       (?=.*\P{L})   # Positive lookahead assertion, is true when there is a non-letter
                                       \S{8,}        # At least 8 non whitespace characters
                                      $              # Match the end of the string
                                    "
, RegexOptions.IgnorePatternWhitespace);

    if (password.Success) {
        Console.WriteLine(s +": valid");
    }
    else {
        Console.WriteLine(s +": invalid");
    }
}

Console.ReadLine();


答案是不要使用正则表达式。这是集合和计数。

正则表达式是关于顺序的。

在你作为程序员的生活中,你会要求做许多没有意义的事情。学习更深入地挖掘一个层次。当问题出了问题时就去学习。

这个问题(如果它提到正则表达式)是错误的。

伪代码(最近在太多语言之间切换):

1
2
3
4
5
6
7
8
9
10
11
12
13
if s.length < 8:
    return False
nUpper = nLower = nAlphanum = nSpecial = 0
for c in s:
    if isUpper(c):
        nUpper++
    if isLower(c):
        nLower++
    if isAlphanumeric(c):
        nAlphanum++
    if isSpecial(c):
        nSpecial++
return (0 < nUpper) and (0 < nAlphanum) and (0 < nSpecial)

当然,你几乎立刻就能读懂上面的代码。当然,你用regex花了很长时间,而且不太确定它是正确的。扩展regex是有风险的。扩展了上面的内容,更不用说这样了。

注意,问题的措词不准确。字符集是ASCII还是Unicode,还是?从阅读问题中我的猜测是至少假定有一个小写字符。所以我认为最后一条规则应该是:

1
return (0 < nUpper) and (0 < nLower) and (0 < nAlphanum) and (0 < nSpecial)

(把帽子换成安全型的,这是一个很烦人/没用的规则。)

学习知道问题是什么时候错的比聪明的答案更重要。对错误问题的巧妙回答几乎总是错误的。


您要查找的正则表达式是:/^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#\$%\^&\*\[\]"\';:_\-<>\., =\+\/\\]).{8,}$/u

示例和测试:http://regexr.com/3fhr4


如果您只需要一个大写字母和特殊字符,那么这应该有效:

1
@"^(?=.{8,}$)(?=[^A-Z]*[A-Z][^A-Z]*$)\w*\W\w*$"


可以使用下面的类进行验证:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class PasswordValidator{

  private Pattern pattern;
  private Matcher matcher;

  private static final String PASSWORD_PATTERN =
         "((?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%]).{6,20})";

  public PasswordValidator(){
      pattern = Pattern.compile(PASSWORD_PATTERN);
  }

  /**
   * Validate password with regular expression
   * @param password password for validation
   * @return true valid password, false invalid password
   */

  public boolean validate(final String password){

      matcher = pattern.matcher(password);
      return matcher.matches();

  }
}

其中6和20是密码的最小和最大长度。


这个问题开始蔓延开来,出现了许多有趣的建议。

是的,手写很难。所以更简单的解决方案是使用模板。虽然最终的regex可能不是最理想的,但是它将更容易维护和/或更改,并且用户将对结果有更好的控制。我可能遗漏了一些东西,所以任何建设性的批评都会有所帮助。

这个链接可能很有趣:在字符串、正则表达式语言、捕获组中,至少匹配2位数字、2个字母的任意顺序

我正在使用这个模板(?=(?:.*?({type})){({count})}),它基于我在so中看到的所有regex。下一步是替换所需的模式(numberspecial character…)并添加长度配置。

我已经为编写regex passwordregexgenerator.cs做了一点准备。一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
string result = new PasswordRegexGenerator ( )
        .UpperCase ( 3, -1 )    // ... {3,}
        .Number ( 2, 4 )        // ... {2,4}
        .SpecialCharacter ( 2 ) // ... {2}
        .Total ( 8,-1 )
        .Compose ( );

/// <summary>
/// Generator for regular expression, validating password requirements.
/// </summary>
public class PasswordRegexGenerator
{
    private string _elementTemplate ="(?=(?:.*?({type})){({count})})";

    private Dictionary<string, string> _elements = new Dictionary<string, string> {
        {"uppercase","[A-Z]" },
        {"lowercase","[a-z]" },
        {"number", @"\d" },
        {"special", @"\W" },
        {"alphanumeric", @"\w" }
    };

    private StringBuilder _sb = new StringBuilder ( );

    private string Construct ( string what, int min, int max )
    {
        StringBuilder sb = new StringBuilder ( _elementTemplate );
        string count = min.ToString ( );

        if ( max == -1 )
        {
            count +=",";
        }
        else if ( max > 0 )
        {
            count +="," + max.ToString();
        }

        return sb
            .Replace ("({type})", what )
            .Replace ("({count})", count )
            .ToString ( );
    }

    /// <summary>
    /// Change the template for the generation of the regex parts
    /// </summary>
    /// <param name="newTemplate">the new template</param>
    /// <returns></returns>
    public PasswordRegexGenerator ChangeRegexTemplate ( string newTemplate )
    {
        _elementTemplate = newTemplate;
        return this;
       }

    /// <summary>
    /// Change or update the regex for a certain type ( number, uppercase ... )
    /// </summary>
    /// <param name="name">type of the regex</param>
    /// <param name="regex">new value for the regex</param>
    /// <returns></returns>
    public PasswordRegexGenerator ChangeRegexElements ( string name, string regex )
    {
        if ( _elements.ContainsKey ( name ) )
        {
            _elements[ name ] = regex;
        }
        else
        {
            _elements.Add ( name, regex );
        }
        return this;
    }

    #region construction methods

    /// <summary>
    /// Adding number requirement
    /// </summary>
    /// <param name="min"></param>
    /// <param name="max"></param>
    /// <returns></returns>
    public PasswordRegexGenerator Number ( int min = 1, int max = 0 )
    {
        _sb.Append ( Construct ( _elements["number" ], min, max ) );
        return this;
    }

    public PasswordRegexGenerator UpperCase ( int min = 1, int max = 0 )
    {
        _sb.Append ( Construct ( _elements["uppercase" ], min, max ) );
        return this;
    }

    public PasswordRegexGenerator LowerCase ( int min = 1, int max = 0 )
    {
        _sb.Append ( Construct ( _elements["lowercase" ], min, max ) );
        return this;
    }

    public PasswordRegexGenerator SpecialCharacter ( int min = 1, int max = 0 )
    {
        _sb.Append ( Construct ( _elements["special" ], min, max ) );
        return this;
    }

    public PasswordRegexGenerator Total ( int min, int max = 0 )
    {
        string count = min.ToString ( ) + ( ( max == 0 ) ?"" :"," + max.ToString ( ) );
        _sb.Append (".{" + count +"}" );
        return this;
    }

    #endregion

    public string Compose ()
    {
        return"(" + _sb.ToString ( ) +")";
    }
}

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