2014-02-13 3 views
0

Я хочу проверить пароль, используя регулярное выражение в C#.Регулярное выражение для проверки пароля C#

Таковы условия:

  1. не должен начинаться с цифры или специального символа
  2. не должен заканчиваться специальным символом
  3. должен содержать любой из этих трех, по крайней мере один раз («@»,» # ',' _ '), и никакие другие специальные символы не допускаются.
  4. должен содержать по крайней мере одну букву
  5. должен содержать по крайней мере одну цифру
  6. длина должна быть не менее 8 символов

Вот моя попытка:

^(?=.*[A-Za-z])(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#_]) 

Я знаю, что это не даже близко, чтобы удовлетворить вышеупомянутым условиям. Поэтому, пожалуйста, кто-нибудь может изменить это регулярное выражение так, чтобы оно удовлетворяло всем вышеперечисленным условиям.

Заранее спасибо.

+7

простой метод C# будет легче читать, проще в обслуживании. –

+2

Не отвечаю на ваш вопрос, но просто хотел упомянуть этот инструмент, который очень полезен для тестирования регулярных выражений ... http://gskinner.com/RegExr/ – KristoferA

+0

Прошу прощения за то, что вы немного не по теме, но это правила 1, 2 и вторая часть 3 («никакие другие специальные символы не разрешены») действительно необходимы? Лично я ненавижу ограничения паролей! И я не вижу причины для них. – gehho

ответ

1

Дайте этот водоворот

^(?i)(?=.*[a-z])(?=.*[0-9])(?=.*[@#_])[a-z][[email protected]#_]{6,}[a-z0-9]$ 

приспосабливает вашу спецификацию я считаю. Из внешнего вида вашего текущего регулярного выражения вы сможете это понять, но если не прокомментировать и плохо объяснить.

+0

Спасибо. Вы можете объяснить эту часть: «[az] [a-z0-9 @ # _] {6} [a-z0-9]" – Ajay

+0

Это будет означать, что пароль может начинаться только с буквы (без цифры или специального символа) [AZ]. Затем еще 6 символов, которые являются либо буквенными буквами, либо @, #, _ [a-z0-9 @ # _] {6}. {6} означает повторение предыдущих пунктов 6 раз. И, наконец, конец не имеет специального символа, поэтому только буква или номер [a-z0-9]. Все это будет 8 символов. – Srb1313711

+0

Кто-то прокомментировал хороший тестер регулярных выражений на ваш вопрос, попробуйте дать ответы на них :-) – Srb1313711

0
^(?=.*[A-Za-z])(?=.*[0-9])(?=.*[@#_])[a-zA-Z][\[email protected]#]{6,}[a-zA-Z0-9]$ 
+0

Спасибо. Вы можете объяснить эту часть: «[a-zA-Z] [\ w @ #] {6,} [a-zA-Z0-9] $" – Ajay

+0

'[a-zA-Z]' = начинается с алфавита. '[\ w @ #] {6,}' = a-zA-Z0-9 _ @ # 6 или более раз. 'a-zA-Z0-9' = буквенно-цифровой в конце. –

+0

'\ w' означает' a-zA-Z0-9_' –

4

Другие предложили вам регулярные ответы и, возможно, это неотъемлемое ограничение вашей проблемы. Однако этот кусок C# делает то, что вы просите, и отличается от обычных выражений тем, что он гораздо читабельнее. Я бы ожидал, что программист младшего уровня сможет его прочитать и понять (и его также легче модифицировать, скажем, не возвращать false, а возвращать null на успех и строку, описывающую, как сбой пароля). Он также работает в O (N) (это незначительная вещь, учитывая, что ваш типичный пароль будет < < 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; 
} 

и прежде, чем вы начнете думать, что я пошел все entertrpisey на вас, вы можете посмотреть на это сразу коде и каждое правило самодокументированно. Его легко модифицировать, он прост в обслуживании. Все правила изолированы друг от друга, и если вы решите использовать stat ic для предикатов, а не лямбда, вы можете легко выполнить каждое правило самостоятельно.

Выполнение этого кода:

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("[email protected]", 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 

Так что если вы беспокоитесь о производительности, это может проверить пароль 1Mb в 62 миллисекунд (на моей машине, которая является довольно мускулистый).

tl; dr - «Некоторые люди, столкнувшись с проблемой, думают« Я знаю, я буду использовать регулярные выражения ». Теперь у них есть две проблемы». - Jamie Zawinksi

Смежные вопросы