C#正则表达式模型验证长度

时间:2014-07-31 19:19:27

标签: c# regex optimization redundancy

问题:如何在不放入所有可能情况的情况下编写此内容?如果某人有一天获得4个密码要求,那么很容易放入,但是很难调试,因为有4个!不同的工作方式。

我如何在代码中使用它:

[RegularExpression("^[A-Za-z0-9!@#$]*([A-Za-z][0-9][!@#$]|[0-9][!@#$][A-Za-z]|[!@#$][A-Za-z][0-9]|[!@#$][0-9][A-Za-z]|[0-9][A-Za-z][!@#$]|[A-Za-z][!@#$][0-9])[A-Za-z0-9!@#$]*$", ErrorMessage = "The Password value must contain at least one letter, one digit, and one special character.")]

为方便观看,我打破了它,所以不需要滚动:

[RegularExpression("^[A-Za-z0-9!@#$]*
([A-Za-z][0-9][!@#$]|[0-9][!@#$][A-Za-z]|
[!@#$][A-Za-z][0-9]|[!@#$][0-9][A-Za-z]|
[0-9][A-Za-z][!@#$]|[A-Za-z][!@#$][0-9])
[A-Za-z0-9!@#$]*$",
ErrorMessage = "The Password value must contain at least one letter,
one digit, and one special character.")]

你可以看到这是3!中间()的可能性由|分隔(或)所以你可以看到4!可能性很难维持。

问题要求:我希望C#中的这个RegularExpression要做的基本事情是要求(没有特别的顺序)至少一个字母,至少一个数字,至少一个特殊字符!,@ ,#或$

1 个答案:

答案 0 :(得分:1)

一个正则表达式

您可以使用零宽度正向前瞻断言(请参阅MSDN's "Regular Expression Language - Quick Reference" - 在“分组构造”部分中)来检查您的ANDed密码要求 - 而无需明确涵盖可能出现所需密码组件的所有订单:

^(?=.*?[a-zA-Z])(?=.*?[0-9])(?=.*?[!@#$]).{3,}$

其工作原理如下:

  • (?=.*?[a-zA-Z]) - 前方发现的字母字符
  • (?=.*?[0-9]) - 提前找到的号码
  • (?=.*?[!@#$]) - 前面允许的特殊字符
  • .{3,} - 总共三个或更多字符

我分享了一个您可能觉得有用的regex fiddle based on this

每个标准的密码检查器

Per @ LeffeBrune的评论,您应该考虑使用专门的密码检查器类来检查,该类根据标准公开属性。

例如,这是一个快速& LINQPad 4中的脏PoC ......

void Main()
{
    var passwords = new string[] {"password", "passw0rd", "passw0rd!", "123456", "!#@$"};

    foreach (var pw in passwords)
    {
        var checker = new PasswordChecker(pw);
        var isValid = checker.IsValid;

        Console.WriteLine("Password {0} is {1}valid.", pw, isValid ? "" : "in");

        if (!isValid)
        {
            Console.WriteLine("    Has alpha?  {0}", checker.HasAlpha ? "Yes." : "NO!");
            Console.WriteLine("    Has number?  {0}", checker.HasNumber ? "Yes." : "NO!");
            Console.WriteLine("    Has special?  {0}", checker.HasSpecial ? "Yes." : "NO!");
            Console.WriteLine("    Has length?  {0}", checker.HasLength ? "Yes." : "NO!");
        }
    }
}

public class PasswordChecker
{
    public const int MINIMUM_LENGTH = 3;
    private string _password;

    public PasswordChecker(string password)
    {
        _password = password;
    }

    public bool HasAlpha
    {
        get
        {
            return Regex.Match(_password, "(?=.*?[a-zA-Z])").Success;
        }
    }

    public bool HasNumber
    {
        get
        {
            return Regex.Match(_password, "(?=.*?[0-9])").Success;
        }
    }

    public bool HasSpecial
    {
        get
        {
            return Regex.Match(_password, "(?=.*?[!@#$])").Success;
        }
    }

    public bool HasLength
    {
        get
        {
            return _password.Length >= MINIMUM_LENGTH;
        }
    }

    public bool IsValid
    {
        get
        {
            return HasLength && HasAlpha && HasNumber && HasSpecial;
        }
    }
}

...产生以下输出:

Password password is invalid.
    Has alpha?  Yes.
    Has number?  NO!
    Has special?  NO!
    Has length?  Yes.
Password passw0rd is invalid.
    Has alpha?  Yes.
    Has number?  Yes.
    Has special?  NO!
    Has length?  Yes.
Password passw0rd! is valid.
Password 123456 is invalid.
    Has alpha?  NO!
    Has number?  Yes.
    Has special?  NO!
    Has length?  Yes.
Password !#@$ is invalid.
    Has alpha?  NO!
    Has number?  NO!
    Has special?  Yes.
    Has length?  Yes.

你可以采取这个快速&当然,更糟糕的是PoC,但希望明白 标准或标准失败的好处是明确的。