Regexp Java для проверки пароля

109

Я создаю регулярное выражение для проверки пароля, которое будет использоваться в приложении Java в качестве параметра конфигурации.

Регулярное выражение:

^.*(?=.{8,})(?=..*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).*$

Политика паролей:

  • Не менее 8 символов

  • Содержит хотя бы одну цифру

  • Содержит как минимум один нижний альфа-символ и один верхний альфа-символ

  • Содержит хотя бы один символ в наборе специальных символов ( @#%$^т. Д.)

  • Не содержит пробелов, табуляции и т. Д.

Мне не хватает только пункта 5. Я не могу проверить регулярное выражение на пробел, табуляцию, возврат каретки и т. Д.

Кто-нибудь может мне помочь?

Kerby82
источник
3
Правила паролей плохие. См. Раздел «Справка - Проверка пароля» для получения дополнительной информации.
ctwheels

Ответы:

317

Попробуй это:

^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\S+$).{8,}$

Пояснение:

^                 # start-of-string
(?=.*[0-9])       # a digit must occur at least once
(?=.*[a-z])       # a lower case letter must occur at least once
(?=.*[A-Z])       # an upper case letter must occur at least once
(?=.*[@#$%^&+=])  # a special character must occur at least once
(?=\S+$)          # no whitespace allowed in the entire string
.{8,}             # anything, at least eight places though
$                 # end-of-string

Добавить, изменить или удалить отдельные правила легко, поскольку каждое правило является независимым «модулем».

(?=.*[xyz])Конструкция съедает всю строку ( .*) и откатывается на первое вхождение , где [xyz]может соответствовать. Успешно, если[xyz] обнаружен, иначе - нет.

Альтернативой было бы использование неохотного квалификатора: (?=.*?[xyz]) . Для проверки пароля это вряд ли будет иметь значение, для гораздо более длинных строк это может быть более эффективным вариантом.

Самым эффективным вариантом (но самым трудным для чтения и поддержки, поэтому наиболее подверженным ошибкам) (?=[^xyz]*[xyz]), конечно же, будет. Для регулярного выражения такой длины и для этой цели я бы не рекомендовал делать это таким образом, поскольку он не имеет реальных преимуществ.

Томалак
источник
15
@ Kerby82: В строках Java обратная косая черта должна быть экранирована. Попробуйте использовать \\s. Это требование Java, а не требование регулярного выражения.
Tomalak
1
@Allov Просто подумайте об этом так: все, что не применяется, необязательно. Просто удалите чеки для вещей, которые вы не хотите применять. Решение должно быть легко адаптировано к вашим потребностям.
Tomalak
3
Этот ответ был добавлен в часто задаваемые вопросы о регулярных выражениях при переполнении стека в разделе «Общие задачи проверки».
aliteralmind
1
@ shA.t Это то же самое. Я только попытался сохранить (?=...)шаблон, чтобы он соответствовал настройке остальной части выражения ..
Tomalak
2
@ shA.t Скажете ли вы «содержит только непробельные символы» ( (?=\S+$)) или «не содержит пробелов» ( (?!.*\s)) - вопрос предпочтения. Используйте то, что вам больше нравится. :)
Tomalak
55

простой пример с использованием регулярного выражения

public class passwordvalidation {
    public static void main(String[] args) {
      String passwd = "aaZZa44@"; 
      String pattern = "(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\\S+$).{8,}";
      System.out.println(passwd.matches(pattern));
   }
}

Пояснения:

  • (?=.*[0-9]) цифра должна встречаться хотя бы один раз
  • (?=.*[a-z]) строчная буква должна встречаться хотя бы один раз
  • (?=.*[A-Z]) заглавная буква должна встречаться хотя бы один раз
  • (?=.*[@#$%^&+=]) специальный символ должен встречаться хотя бы один раз
  • (?=\\S+$) во всей строке не допускаются пробелы
  • .{8,} минимум 8 символов
проворный
источник
5
. {5,10} представляет минимум 5 символов и максимум 10 символов. На всякий случай кто-то ищет конкретного объяснения.
abhy
@iabhi, я это искал. Спасибо.
Акшата Шринивас
Я пытаюсь реализовать Regex для пароля, хранящегося в массиве char, а не в String из-за безопасности. Но как применить регулярное выражение к массиву символов?
AgentM 08
13

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

Я начну с регулярного выражения из принятого ответа:

^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\S+$).{8,}$

Прежде всего, поскольку Java поддерживает, \Aи \zя предпочитаю использовать их, чтобы убедиться, что вся строка проверена независимо от Pattern.MULTILINE. Это не влияет на производительность, но позволяет избежать ошибок при повторном использовании регулярных выражений.

\A(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\S+$).{8,}\z

Проверить, не содержит ли пароль пробелов и проверить его минимальную длину, можно за один проход, используя все сразу, указав квантификатор переменной {8,}в сокращении \S, ограничивающем допустимые символы:

\A(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])\S{8,}\z

Если предоставленный пароль действительно содержит пробел, все проверки будут выполнены только для того, чтобы окончательная проверка не прошла. Этого можно избежать, заменив все точки на \S:

\A(?=\S*[0-9])(?=\S*[a-z])(?=\S*[A-Z])(?=\S*[@#$%^&+=])\S{8,}\z

Точку следует использовать только в том случае, если вы действительно хотите разрешить использование любого символа. В противном случае используйте (отрицательный) класс символов, чтобы ограничить ваше регулярное выражение только теми символами, которые действительно разрешены. Хотя в данном случае это не имеет большого значения, не использовать точку, когда что-то более подходящее - очень хорошая привычка. Я вижу слишком много случаев катастрофического отката, потому что разработчик был слишком ленив, чтобы использовать что-то более подходящее, чем точка.

Поскольку есть большая вероятность, что начальные тесты найдут подходящий символ в первой половине пароля, ленивый квантификатор может быть более эффективным:

\A(?=\S*?[0-9])(?=\S*?[a-z])(?=\S*?[A-Z])(?=\S*?[@#$%^&+=])\S{8,}\z

Но теперь перейдем к действительно важному вопросу: ни в одном из ответов не упоминается тот факт, что исходный вопрос, похоже, написан кем-то, кто мыслит в ASCII. Но в Java строки - это Unicode. Допускаются ли в паролях символы, отличные от ASCII? Если да, то запрещены только пробелы ASCII или все пробелы Unicode должны быть исключены.

По умолчанию \sсоответствует только пробелам ASCII, поэтому его инверсия \Sсоответствует всем символам Unicode (пробелам или нет) и всем непробельным символам ASCII. Если символы Unicode разрешены, а пробелы Unicode - нет, UNICODE_CHARACTER_CLASSможно указать флаг, чтобы \Sисключить пробелы Unicode. Если символы Юникода недопустимы, [\x21-\x7E]их можно использовать вместо\S сопоставления всех символов ASCII, не являющихся пробелами или управляющими символами.

Это подводит нас к следующей потенциальной проблеме: хотим ли мы разрешить использование управляющих символов? Первый шаг в написании правильного регулярного выражения - точно указать, что вы хотите сопоставить, а что нет. Единственный 100% технически правильный ответ состоит в том, что спецификация пароля в вопросе неоднозначна, поскольку в нем не указано, разрешены ли определенные диапазоны символов, такие как управляющие символы или символы, отличные от ASCII.

Ян Гойвертс
источник
9

Вы не должны использовать слишком сложные регулярные выражения (если вы можете их избежать), потому что они

  • трудно читать (по крайней мере, для всех, кроме себя)
  • трудно продлить
  • трудно отлаживать

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

Я бы реализовал так:

bool matchesPolicy(pwd) {
    if (pwd.length < 8) return false;
    if (not pwd =~ /[0-9]/) return false;
    if (not pwd =~ /[a-z]/) return false;
    if (not pwd =~ /[A-Z]/) return false;
    if (not pwd =~ /[%@$^]/) return false;
    if (pwd =~ /\s/) return false;
    return true;
}
Мартин Раушер
источник
А с точки зрения безопасности гораздо лучше принудительно использовать более длинные пароли, предотвращать использование хорошо известных паролей (например, 12345 и pass = user) вместо того, чтобы делать пароли сверхсложными и трудными для запоминания.
Мартин Раушер
Мне нравится ваш подход выше. Спасибо вам за это!
Thomas Lang
1

Требование пароля:

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

    ^.*(?=.{8,})(?=.*\d)(?=.*[a-zA-Z])|(?=.{8,})(?=.*\d)(?=.*[!@#$%^&])|(?=.{8,})(?=.*[a-zA-Z])(?=.*[!@#$%^&]).*$

Я протестировал и он работает

Андрей
источник
1

Для всех, кто интересуется минимальными требованиями для каждого типа персонажа, я бы предложил сделать следующее расширение принятого ответа Томалака:

^(?=(.*[0-9]){%d,})(?=(.*[a-z]){%d,})(?=(.*[A-Z]){%d,})(?=(.*[^0-9a-zA-Z]){%d,})(?=\S+$).{%d,}$

Обратите внимание, что это строка форматирования, а не последний шаблон регулярного выражения. Просто замените% d минимально необходимым количеством вхождений для: цифр, строчных, прописных, нецифровых / символов и всего пароля (соответственно). Максимальное количество появлений маловероятно (если вы не хотите, чтобы максимальное значение было равно 0, что эффективно отклоняет любые такие символы), но их также можно легко добавить. Обратите внимание на дополнительную группировку вокруг каждого типа, так что ограничения min / max допускают непоследовательные совпадения. Это творило чудеса для системы, в которой мы могли централизованно настраивать количество требуемых символов каждого типа, а затем веб-сайт, а также две разные мобильные платформы извлекали эту информацию для создания шаблона регулярного выражения на основе указанной выше строки форматирования.

Деметриос Кристофер
источник
1

Этот проверяет каждый специальный символ:

^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=\S+$).*[A-Za-z0-9].{8,}$
Ансу
источник
1

Готовый для вас метод Java с параметрами

Просто скопируйте и вставьте и установите желаемые параметры.

Если вам не нужен модуль, просто прокомментируйте его или добавьте «если», как я сделал для специального символа

//______________________________________________________________________________
/**
 * Validation Password     */
//______________________________________________________________________________
private static boolean validation_Password(final String PASSWORD_Arg)    {
    boolean result = false;
    try {
        if (PASSWORD_Arg!=null) {
            //_________________________
            //Parameteres
            final String MIN_LENGHT="8";
            final String MAX_LENGHT="20";
            final boolean SPECIAL_CHAR_NEEDED=true;

            //_________________________
            //Modules
            final String ONE_DIGIT = "(?=.*[0-9])";  //(?=.*[0-9]) a digit must occur at least once
            final String LOWER_CASE = "(?=.*[a-z])";  //(?=.*[a-z]) a lower case letter must occur at least once
            final String UPPER_CASE = "(?=.*[A-Z])";  //(?=.*[A-Z]) an upper case letter must occur at least once
            final String NO_SPACE = "(?=\\S+$)";  //(?=\\S+$) no whitespace allowed in the entire string
            //final String MIN_CHAR = ".{" + MIN_LENGHT + ",}";  //.{8,} at least 8 characters
            final String MIN_MAX_CHAR = ".{" + MIN_LENGHT + "," + MAX_LENGHT + "}";  //.{5,10} represents minimum of 5 characters and maximum of 10 characters

            final String SPECIAL_CHAR;
            if (SPECIAL_CHAR_NEEDED==true) SPECIAL_CHAR= "(?=.*[@#$%^&+=])"; //(?=.*[@#$%^&+=]) a special character must occur at least once
            else SPECIAL_CHAR="";
            //_________________________
            //Pattern
            //String pattern = "(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\\S+$).{8,}";
            final String PATTERN = ONE_DIGIT + LOWER_CASE + UPPER_CASE + SPECIAL_CHAR + NO_SPACE + MIN_MAX_CHAR;
            //_________________________
            result = PASSWORD_Arg.matches(PATTERN);
            //_________________________
        }    

    } catch (Exception ex) {
        result=false;
    }

    return result;
}        
Фаусто70
источник
1

Используйте библиотеку Passay, которая является мощным API.

Баласубраманская ренгасами
источник
0

Я думаю, что это тоже можно сделать (в более простом режиме):

^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])[^\s]{8,}$

[Демо Regex]

shA.t
источник
0

легкий

("^ (? =. * [0-9]) (? =. * [Az]) (? =. * [AZ]) (? =. * [\\ W _]]» [\\ S] {8 , 10} $ ")

  1. (? = что угодно) -> означает положительный взгляд вперед во всей входной строке и убедитесь, что это условие записано .sample (? =. * [0-9]) -> означает, что во всей строке записано однозначное число. если не написано, вернуть false .

  2. (?! что угодно) -> (наоборот) означает отрицательный взгляд вперед, если записано условие return false .

    близкий смысл ^ (условие) (условие) (условие) (условие) [\ S] {8,10} $

ибрахем шаббан
источник
В то время как ответы только на код могут предоставить решение проблемы, некоторые пояснения могут значительно улучшить качество ответа.
Найджел Рен
0
String s=pwd;
int n=0;
for(int i=0;i<s.length();i++)
{
    if((Character.isDigit(s.charAt(i))))
    {
        n=5;
        break;
    }
    else
    {

    }
}
for(int i=0;i<s.length();i++)
{
    if((Character.isLetter(s.charAt(i))))
    {
        n+=5;
        break;
    }
    else
    {

    }

}

if(n==10)
{
    out.print("Password format correct <b>Accepted</b><br>");

}
else
{
    out.print("Password must be alphanumeric <b>Declined</b><br>");
}

Пояснение:

  1. Сначала установите пароль в виде строки и создайте целочисленный набор o.
  2. Затем проверьте каждый символ цикла for.
  3. Если он находит число в строке, то n добавляет 5. Затем переходите к следующему циклу for. Character.isDigit (s.charAt (i))
  4. Этот цикл проверяет все алфавиты, помещенные в строку. Если его находят, добавьте еще 5 в n. Character.isLetter (s.charAt (i))
  5. Теперь проверьте целое число n с помощью условия if. Если n = 10 верно, данная строка является буквенно-цифровой, иначе - нет.
Нареш Бабу
источник
0

Также вы можете это сделать.

 public boolean isPasswordValid(String password) {


    String regExpn =
            "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\\S+$).{8,}$";

    CharSequence inputStr = password;

    Pattern pattern = Pattern.compile(regExpn,Pattern.CASE_INSENSITIVE);
    Matcher matcher = pattern.matcher(inputStr);

    if(matcher.matches())
        return true;
    else
        return false;
}
РАНАДЖИТ БАРИК
источник
0

Пример блока кода для надежного пароля:

(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9])(?=\\S+$).{6,18}
  1. минимум 6 цифр
  2. до 18 цифр
  3. один номер
  4. одна строчная буква
  5. одна заглавная буква
  6. может содержать все специальные символы
Седреттин Чалышкан
источник
0

RegEx - это -

^(?:(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).*)[^\s]{8,}$
  1. не менее 8 цифр {8,}
  2. хотя бы одно число (? =. * \ d)
  3. хотя бы одна строчная буква (? =. * [az])
  4. хотя бы один верхний регистр (? =. * [AZ])
  5. хотя бы один специальный символ (? =. * [@ # $% ^ & + =])
  6. Нет места [^ \ s]
Анкит Кумар Раджпут
источник