2016-05-04 2 views
-1

мне нужно проверить строку пароля с этими правилами:Есть ли способ объединить эти два регулярных выражения?

  • только строчные буквы, прописные буквы, цифры и некоторые специальные символы (смотри ниже) допускаются.
  • Minimun 8 символов и не более 16
  • Пароль должен содержит по крайней мере один символ из трех из четырех следующих групп:

    • строчной буквы
    • прописной буквы
    • Числовой символ
    • Специальный символ (@ # $% &/= _!? ;-).

Для достижения этой цели я сделал две проверки. Легко один первый шаг, проверьте допустимые символы и клыков:

^[[email protected]\#$%&/=?_.,:;\-]{8,16}$ 

второй один является немного более сложным, но я мог бы решить его благодаря этому Stackoverflow answer:

^((?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])|(?=.*[a-z])(?=.*[A-Z])(?=.*[[email protected]\#$%&/=?_.,:;\-])|(?=.*[a-z])(?=.*[0-9])(?=.*[[email protected]\#$%&/=?_.,:;\-])|(?=.*[A-Z])(?=.*[0-9])(?=.*[[email protected]\#$%&/=?_.,:;\-])).{8,16}$ 

Я думаю, что, вероятно, решение с двумя шагами ясное и простое ... но ... Есть ли способ объединить оба регулярных выражения?

Я хотел бы применить решение на Java, JavaScript и Lua.

ответ

1

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

Я написал это регулярное выражение в расширенной форме (т.е. игнорирует пробельные), для ясности:

/\A 
    (?=.{8,16}\z)      # Must contain 8-16 characters 
    (?!.*[^a-zA-Z\[email protected]#$%&\/=?_.,:;-]) # Must not contain other characters 
    (?=.*\d)       # Must contain a digit 
    (?=.*[a-z])      # Must contain a lower case character 
    (?=.*[A-Z])      # Must contain an upper case character 
    (?=.*[[email protected]#$%&\/=?_.,:;-])   # Must contain a symbol from this list 
/x 

, приведенный выше шаблон решает проблему для соблюдения все четыре ваших правил. Теоретически вы могли бы обернуть последние 4 условия в четыре «или» группы, как это сделал ваш оригинальный пример.

Однако, опять же, я бы не рекомендовал его. Ваш код будет гораздо более разборчивым, полезным и удобным, если вы сделаете это как серию отдельных проверок внутри функции. (Например, это означает, что вы можете отображать более полезные сообщения об ошибках, а не просто «regex failed!».

Но так как вы спросили ...Вот регулярное выражение монстра:

/\A 
    (?=.{8,16}\z) 
    (?!.*[^a-zA-Z\[email protected]#$%&\/=?_.,:;-]) 
    (
    (?=.*\d) 
    (?=.*[a-z]) 
    (?=.*[A-Z]) 
    | 
    (?=.*\d) 
    (?=.*[a-z]) 
    (?=.*[[email protected]#$%&\/=?_.,:;-]) 
    | 
    (?=.*\d) 
    (?=.*[A-Z]) 
    (?=.*[[email protected]#$%&\/=?_.,:;-]) 
    | 
    (?=.*[a-z]) 
    (?=.*[A-Z]) 
    (?=.*[[email protected]#$%&\/=?_.,:;-]) 
) 
/x 

Удалить все пробелы, если вы не хотите/иметь доступ к модификатором /x.

+0

Политика паролей является обязательным требованием к моей проблеме, и он реализовал эту политику в других системах, поэтому ее очень сложно изменить в настоящее время. Спасибо @TomLord за ваше решение и советы! –

0

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

public static void main(String[] args) { 
    System.out.println(isPasswordValid("Ab$123456")); 
    System.out.println(isPasswordValid("b$11234566")); 
    System.out.println(isPasswordValid("Ab$1234634634534252")); 
    System.out.println(isPasswordValid("$112512312512")); 
    System.out.println(isPasswordValid("A$115 223")); 
} 

private static boolean isPasswordValid(String password) { 
    // The password is to short or to long 
    if(password.length() < 8 || password.length() > 16) { 
     return false; 
    } 
    int matchedConditions = 0; 
    // Check for invalid characters 
    if(password.matches(".*[^[email protected]#$%&/=?_.,:;-].*")) { 
     return false; 
    } 
    // is an uppercase letter present, increase matched condition 
    if(password.matches(".*[A-Z].*")){ 
     ++matchedConditions; 
    } 
    // is a lowercase letter present, increase matched condition 
    if(password.matches(".*[a-z].*")){ 
     ++matchedConditions; 
    } 
    // is a numeric value present, increase matched condition 
    if(password.matches(".*[0-9].*")){ 
     ++matchedConditions; 
    } 
    // is a special character present, increase matched condition 
    if(password.matches(".*[[email protected]#$%&/=?_.,:;-].*")){ 
     ++matchedConditions; 
    } 
    // Return if at least 3 conditions were met 
    return matchedConditions >= 3; 
} 

выход:

true 
true 
false 
false 
false 
+0

Спасибо, но ваше решение вернет true для этого пароля 'Ab $ 12 34', а пробелы не разрешены, не так ли? –

+0

@DavidIsla проверить мое редактирование, все равно гораздо лучше читать, если вы включили список для недопустимого символа, где вы могли бы включить все, что вы не считаете действительным. – SomeJavaGuy

+0

Конечно, ваше решение действительно, это правильно, но я хочу знать, есть ли способ объединить оба. Большое спасибо! –

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