【问题标题】:C# RegularExpression Model Validation LengthC# 正则表达式模型验证长度
【发布时间】:2014-07-31 19:19:26
【问题描述】:

问题:如何在不考虑所有可能情况的情况下编写此内容?如果有一天有人收到 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# 中的正则表达式做的基本事情是要求(不分先后)至少一个字母,至少一个数字,至少一个特殊字符!,@ 、# 或 $

【问题讨论】:

  • 试图提高正则表达式的可读性不是这里要走的路。将您的密码检查包装到有意义命名的类/方法中,这些类/方法会将您隐藏在代码的高级视图中。
  • Check out this page 并告诉您是否有帮助。问题中的正则表达式应该是您要查找的正则表达式。如果不是,请尝试澄清您的问题
  • 顺便说一句,像这样的密码策略几乎是普遍愚蠢的:xkcd.com/936 我同意虽然你可以用正则表达式来做到这一点,但试图让正则表达式更具可读性并不是解决问题的方法去。把它当成一个有规则的策略,一个一个地验证规则。您可以告诉用户哪些愚蠢的策略规则没有被遵守。使用正则表达式更难做到这一点。
  • 我目前正在通过 jQuery 通过客户端执行此操作,我可以在其中说“嘿,您的密码至少缺少一个 {字母|数字|特殊字符}。”现在我正在尝试使用模型验证来充分利用 MVC 框架,而不是过多地依赖 jQuery。我查看了您链接的漫画,但这是一个已实施的验证检查,我只是试图进入模型验证而不是带有警报消息的 jQuery。

标签: c# regex optimization redundancy


【解决方案1】:

一个正则表达式

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

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

它的工作原理如下:

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

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

Property-Per-Criterion 密码检查器

根据@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 做得更进一步,但了解什么标准或标准失败的好处希望是显而易见的。

【讨论】:

  • 太棒了!这确实有效。我正在做一个类似的正则表达式,但我离开了 .{3,} 部分,当添加它时它起作用了。我的看起来和你的一模一样,只是我在 [!@#$] 之后没有 +,真的需要吗?
  • @johnatrik:很好地抓住了[!@#$] 之后挥之不去的+。在我列出的细分中,我没有它;但我把它留在了完整的模式中,这不是我想要的。不,没有必要,我已将其从完整模式和相关小提琴中删除。
猜你喜欢
  • 2020-06-19
  • 2022-11-23
  • 2023-03-28
  • 1970-01-01
  • 1970-01-01
  • 2017-12-16
  • 2011-08-08
  • 2014-05-08
  • 2014-04-23
相关资源
最近更新 更多