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

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

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

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

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

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

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

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

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

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

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

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

17 ответов

Решение

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

^(?=.*[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]), конечно. Для регулярного выражения этой длины и для этой цели я бы не рекомендовал делать это таким образом, так как он не имеет реальных преимуществ.

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

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 символов

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

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

^(?=.*[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_CHARACTER_CLASS флаг может быть указан, чтобы сделать \S исключить пробел Unicode. Если символы Юникода не разрешены, то [\x21-\x7E] можно использовать вместо \S соответствовать всем символам ASCII, которые не являются пробелом или управляющим символом.

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

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

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

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

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

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;
}

Спасибо за все ответы, основанные на всех, кроме расширенных сферических персонажей:

      String PASSWORD_SPECIAL_CHARS = "@#$%^`<>&+=\"!ºª·#~%&'¿¡€,:;*/+-.=_\\[\\]\\(\\)\\|\\_\\?\\\\";
int PASSWORD_MIN_SIZE = 8;
String PASSWORD_REGEXP = "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[" + PASSWORD_SPECIAL_CHARS + "])(?=\\S+$).{"+PASSWORD_MIN_SIZE+",}$";

Единичные испытания:

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

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

Метод 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;
}        

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

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

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

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

Я проверил это, и это работает

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

 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-9]){%d,})(?=(.*[a-z]){%d,})(?=(.*[A-Z]){%d,})(?=(.*[^0-9a-zA-Z]){%d,})(?=\S+$).{%d,}$

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

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

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

[Regex Demo]

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. Затем проверьте каждый символ для цикла.
  3. Если он находит число в строке, то n добавляет 5. Затем переходите к следующему циклу for. Character.isDigit (s.charAt (я))
  4. Этот цикл проверяет любые алфавиты, помещенные в строку. Если его найти, то добавьте еще 5 в n. Character.isLetter (s.charAt (я))
  5. Теперь проверьте целое число n с помощью условия if. Если n=10 истинно, данная строка является буквенно-цифровой, иначе это не так.

RegEx - это -

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

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

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

Легкий

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

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

    близкое значение ^ (условие) (условие) (условие) (условие)[\ S] {8,10}$

Более общий ответ, который принимает все специальные символы, включая _ будет немного иначе:

^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[\W|\_])(?=\S+$).{8,}$

Разница (?=.*[\W|\_]) переводится как «хотя бы один из всех специальных символов, включая подчеркивание».

Другие вопросы по тегам