我想在c#中使用正则表达式验证密码。
以下是条件:
这是我的尝试:
^(?=.*[A-Za-z])(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#_])
我知道它甚至不能满足上述条件。所以,任何人都可以修改这个正则表达式,以满足上述所有条件。
提前致谢。
答案 0 :(得分:4)
其他人已经为你提出了正则表达式的答案,也许这是你问题的不可动摇的约束。但是,这个C#块做了你所要求的,并且与正则表达式的不同之处在于它更具可读性。我希望初级程序员能够阅读并理解它(并且更容易将其修改为,例如,不返回false但成功时返回null,以及描述密码失败的字符串)。它也在O(n)中运行(考虑到您的典型密码将<&lt; <100个字符,这是一个小问题。
private const int kMinimumLength = 8;
private static string _specialChars = "@#_";
private static bool IsSpecialChar(char c) { return _specialChars.IndexOf(c) >= 0; }
private static bool IsValidPasswordChar(char c) { return IsSpecialChar(c) || Char.IsLetterOrDigit(c); }
public static bool IsPasswordValid(string password)
{
if (password == null || password.Length < kMinimumLength || IsSpecial(password[0])
|| IsSpecial(password[password.Length - 1]))
return false;
bool hasLetter = false, hasDigit = false;
int specials = 0;
foreach (char c in password)
{
hasDigit = hasDigit || Char.IsDigit(c);
hasLetter = hasLetter || Char.IsLetter(c);
specials += IsSpecialChar(c) ? 1 : 0;
if (!IsValidPasswordChar(c)) return false;
}
return hasDigit && hasLetter && specials > 1;
}
现在,如果您考虑这个过程并理解在这样一个小问题域中,您可能会因为可读性而做得更好:
public class Rule {
public Func<string, bool> Predicate { get; set; }
public string Description { get; set; }
}
private List<Rule> rules = new List<Rule>() {
new Rule(){ Predicate = (s => s != null),
Description = "Password must not be null" },
new Rule(){ Predicate = (s => s.Length >= kMinimumLength ),
Description = "Password must have at least " + kMinimumLength + " characters." },
new Rule(){ Predicate = (s => s.Count(c => IsSpecialChar(c)) >= 1),
Description = "Password must contain at least one of " + _specialChars },
new Rule(){ Predicate = (s => !IsSpecialChar(s[0]) && !IsSpecialChar(s[s.Length - 1])),
Description = "Password must not start or end with " + _specialChars },
new Rule(){ Predicate = (s => s.Count(c => Char.IsLetter(c)) > 0),
Description = "Password must contain at least one letter." },
new Rule(){ Predicate = (s => s.Count(c => Char.IsDigit(c)) > 0),
Description = "Password must contain at least one digit." },
new Rule(){ Predicate = (s =>s.Count(c => !IsValidPasswordChar(c)) == 0),
Description = "Password must contain letters, digits, or one of " + _specialChars }
}
public bool IsPasswordValid(string s, ref string failureReason)
{
foreach (Rule r in rules) {
if (!r.Predicate(s)) {
failureReason = r.Description;
return false;
}
}
return true;
}
在你开始认为我已经完全了解你之前,你可以立即查看这些代码,每条规则都是自我记录的。它很容易修改。它易于维护。所有规则都是相互隔离的,如果你选择使用静态方法代替lambdas,你可以轻松地单独测试每个规则。
运行此代码:
static void Main(string[] args)
{
string reason = null;
if (!IsPasswordValid(null, ref reason)) Console.WriteLine(reason);
if (!IsPasswordValid("", ref reason)) Console.WriteLine(reason);
if (!IsPasswordValid("aaaaaaaa", ref reason)) Console.WriteLine(reason);
if (!IsPasswordValid("_aaaaaaa", ref reason)) Console.WriteLine(reason);
if (!IsPasswordValid("aaaaaaa_", ref reason)) Console.WriteLine(reason);
if (!IsPasswordValid("1aaa!aaa", ref reason)) Console.WriteLine(reason);
if (!IsPasswordValid("11111111", ref reason)) Console.WriteLine(reason);
if (!IsPasswordValid("a1a1a1a1", ref reason)) Console.WriteLine(reason);
if (!IsPasswordValid("a1a1@1a1", ref reason)) Console.WriteLine(reason);
StringBuilder sb = new StringBuilder();
sb.Append('a');
for (int i = 0; i < 1000000; i++) { sb.Append('@'); }
sb.Append('a');
sb.Append('1');
string pass = sb.ToString();
long ticks = Environment.TickCount;
if (IsPasswordValid(pass, ref reason)) Console.WriteLine("Valid.");
long endticks = Environment.TickCount;
Console.WriteLine("Time elapsed: " + (endticks - ticks));
}
给出:
Password must not be null
Password must have at least 8 characters.
Password must contain at least one of @#_
Password must not start or end with @#_
Password must not start or end with @#_
Password must contain at least one of @#_
Password must contain at least one of @#_
Password must contain at least one of @#_
Valid.
Time elapsed: 62
因此,如果您担心性能问题,可以在62毫秒内检查1Mb密码(在我的机器上,这非常强大)。
tl; dr - “有些人在遇到问题时会想:”我知道,我会使用正则表达式。“现在他们有两个问题。” - Jamie Zawinksi
答案 1 :(得分:1)
给它一个旋转
^(?i)(?=.*[a-z])(?=.*[0-9])(?=.*[@#_])[a-z][a-z0-9@#_]{6,}[a-z0-9]$
符合您的规格我相信。从你当前的正则表达式的外观,你将能够理解它,但如果没有评论和不解释。
答案 2 :(得分:0)
^(?=.*[A-Za-z])(?=.*[0-9])(?=.*[@#_])[a-zA-Z][\w@#]{6,}[a-zA-Z0-9]$