Регулярное выражение для проверки, состоит ли пароль из «8 символов, включая 1 заглавную букву, 1 специальный символ, буквенно-цифровые символы».


102

Я хочу, чтобы регулярное выражение проверяло это

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

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

(?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$"

Как я могу написать это для пароля, который должен состоять из восьми символов, включая одну заглавную букву, один специальный символ и буквенно-цифровые символы?


26
Зачем для этого нужно регулярное выражение? Полное регулярное выражение, соответствующее вашим требованиям, будет очень длинным и сложным. В коде C # проще писать ограничения.
Грег Хьюгилл

33
Рассматривали ли вы возможность проверки надежного пароля вместо проверки соответствия пароля некоторым произвольным правилам, которые являются несовершенным прокси для надежного пароля? Существует множество библиотек и программ, которые при вводе пароля определяют его надежность.
Уэйн Конрад,

4
@GregHewgill Я бы поддержал ваш комментарий, если бы мог :-) Это похоже на еще один случай, когда «если у вас есть только молоток, все начинает выглядеть как гвоздь».
Christian.K

3
Вам нужен ровно один прописной / специальный символ или хотя бы один?
mmdemirbas

4
Под требованиями пользователя вы имеете в виду, что ваш пользователь диктует детали реализации? Возможно, тогда им стоит просто написать это сами. Честно говоря, я думаю, что было бы легче поддерживать и понимать, если бы вы просто создавали счетчики и проверяли каждый символ один за другим, увеличивая соответствующие счетчики для каждого символа, который соответствует правилу. С технической точки зрения это не то, что никого впечатлит, но зачем усложнять вещи чем-то, что будет подвержено ошибкам и будет сложно обновлять?

Ответы:


132

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

Я думаю, было бы проще сломать ваше регулярное выражение и делать это по частям. Это может занять немного больше времени, но я почти уверен, что поддерживать его и отлаживать будет проще. Это также позволит вам предоставлять более конкретные сообщения об ошибках вашим пользователям (не только Invalid Password), что должно улучшить взаимодействие с пользователем.

Из того, что я вижу, вы довольно свободно владеете регулярными выражениями, поэтому я предполагаю, что давать вам регулярные выражения для выполнения того, что вам нужно, было бы бесполезно.

Увидев ваш комментарий, я бы сделал следующее:

  • Должен состоять из восьми символов. Длинный: для этого не требуется регулярное выражение. .LengthДостаточно использовать собственность.

  • Включая одну заглавную букву: вы можете использовать [A-Z]+регулярное выражение. Если строка содержит хотя бы одну заглавную букву, это регулярное выражение даст результат true.

  • Один специальный символ: вы можете использовать либо, \Wкоторый будет соответствовать любому символу, не являющемуся буквой или цифрой, либо вы можете использовать что-то подобное, чтобы [!@#]указать собственный список специальных символов. Обратите внимание , однако , что такие символы, как $, ^, (и )специальные символы в языке регулярных выражений, поэтому они должны быть экранированы , как так: \$. Короче говоря, вы можете использовать расширение \W.

  • Буквенно-цифровые символы: использование символа \w+должно соответствовать любой букве, цифре и знаку подчеркивания.

Взгляните на это руководство для получения дополнительной информации.


2
Я не писал это сам, я получил это от Google, дорогой друг
Рания Умайр

4
@RaniaUmair: Думаю, ваш комментарий подтверждает мою точку зрения. Я бы порекомендовал вам разбить его, как я указал.
npinti


@ w0lf: Я не могу не согласиться. Регулярное выражение - мощное средство, однако оно слишком быстро становится слишком сложным, поэтому лучше не усложнять его.
npinti

Можете ли вы помочь мне, мне нужен regx, который принимает хотя бы одно число, а максимум 3 других символа могут быть
любыми

107
(                   # Start of group
    (?=.*\d)        #   must contain at least one digit
    (?=.*[A-Z])     #   must contain at least one uppercase character
    (?=.*\W)        #   must contain at least one special symbol
       .            #     match anything with previous condition checking
         {8,8}      #        length is exactly 8 characters
)                   # End of group

В одной строке:

((?=.*\d)(?=.*[A-Z])(?=.*\W).{8,8})

Изменить 2019-05-28:

Вам нужно сопоставить всю строку ввода. Таким образом, вы можете заключить регулярное выражение между ^и, $чтобы предотвратить случайное принятие частичных совпадений как совпадающих со всем вводом:

^((?=.*\d)(?=.*[A-Z])(?=.*\W).{8,8})$

Источники:


58
Потому что он состоит из 12 символов
mmdemirbas

еще одно условие не должно начинаться с цифры, как я могу это сделать?
Lijo 06

7
Вместо этого вы можете сократить его, используя {8}, чтобы соответствовать 8 символам
Анджело Трикарико,

его соответствие для $ 1eerrrrrrr .. в нем нет заглавной буквы.
Шилпи Джайсвал

@ShilpiJaiswal Либо вы используете флаг для сопоставления без учета регистра, либо выполняете «найти» вместо «сопоставления». Чтобы обеспечить соответствие всей входной строке, вы можете заключить регулярное выражение между ^и $. Попробуйте это:^((?=.*\d)(?=.*[A-Z])(?=.*\W).{8,8})$
mmdemirbas

35

Столько ответов .... все плохо!

Регулярные выражения не имеют оператора И, поэтому довольно сложно написать регулярное выражение, которое соответствует действительным паролям, когда действительность определяется чем-то И чем-то еще И чем-то еще ...

Но регулярные выражения делать есть оператор ИЛИ, так просто применить теорему де Морган, и написать регулярное выражение , которое соответствует недопустимым паролям.

что-либо, содержащее менее 8 символов, ИЛИ что-либо без цифр, ИЛИ что-либо без верхнего регистра ИЛИ что-либо без специальных символов

Так:

^(.{0,7}|[^0-9]*|[^A-Z]*|[a-zA-Z0-9]*)$

Если что-то соответствует этому, то это недействительный пароль.


3
Если OP хочет ровно 8 символов, вам нужно добавить |.{9,}. +1 за концепцию
Даниэль

Отличное и простое решение вопроса, хотя я согласен, что одно регулярное выражение не является оптимальным для реальной проблемы.
Siderite Zackwehdex

1
Регулярные выражения действительно есть и операторы, они называются LOOKAHEAD / Утверждения касательно предшествующего текста.
relative_random

13

Ответ - не использовать регулярное выражение. Это наборы и подсчет.

Регулярные выражения говорят о порядке.

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

Вопрос (упоминались ли регулярные выражения) неверен.

Псевдокод (в последнее время переключался между слишком большим количеством языков):

if s.length < 8:
    return False
nUpper = nLower = nAlphanum = nSpecial = 0
for c in s:
    if isUpper(c):
        nUpper++
    if isLower(c):
        nLower++
    if isAlphanumeric(c):
        nAlphanum++
    if isSpecial(c):
        nSpecial++
return (0 < nUpper) and (0 < nAlphanum) and (0 < nSpecial)

Спорим, вы прочитали и поняли приведенный выше код почти мгновенно. Спорим, вы потратили намного больше времени на регулярное выражение и менее уверены в его правильности. Расширять регулярное выражение рискованно. Расширенное непосредственно выше, тем более.

Обратите внимание, что вопрос сформулирован неточно. Это набор символов ASCII или Unicode, или ?? Я предполагаю, читая вопрос, что предполагается хотя бы один символ нижнего регистра. Итак, я думаю, что предполагаемое последнее правило должно быть:

return (0 < nUpper) and (0 < nLower) and (0 < nAlphanum) and (0 < nSpecial)

(Смена головных уборов на ориентированные на безопасность - это действительно раздражающее / бесполезное правило.)

Умение распознавать неправильный вопрос гораздо важнее умных ответов. Умный ответ на неправильный вопрос почти всегда неверен.


2
Я согласен. Чем больше людей вы работаете, тем больше кода нужно читать, хотя некоторые реализации регулярных выражений, которые я видел в качестве ответов, довольно ясны
Никола Пелучетти

Мне нравится, что некоторые пользователи, такие как вы, имеют смелость сказать, что Regex не всегда является лучшим решением для применения и что иногда простое программирование более читабельно.
Schlebe,

12

В качестве примера, как это можно сделать с помощью читаемого / поддерживаемого регулярного выражения.

Для более длинного регулярного выражения вы всегда должны использовать, RegexOptions.IgnorePatternWhitespaceчтобы разрешить пробелы и комментарии в выражении для лучшей читаемости.

String[] passwords = { "foobar", "Foobar", "Foobar1", "Fooobar12" };

foreach (String s in passwords) {

    Match password = Regex.Match(s, @"
                                      ^              # Match the start of the string
                                       (?=.*\p{Lu})  # Positive lookahead assertion, is true when there is an uppercase letter
                                       (?=.*\P{L})   # Positive lookahead assertion, is true when there is a non-letter
                                       \S{8,}        # At least 8 non whitespace characters
                                      $              # Match the end of the string
                                     ", RegexOptions.IgnorePatternWhitespace);

    if (password.Success) {
        Console.WriteLine(s + ": valid");
    }
    else {
        Console.WriteLine(s + ": invalid");
    }
}

Console.ReadLine();

Это лучший способ злоупотребить lookahead assertionшаблоном as вида «и», чтобы охватить все ограничение в одном регулярном выражении. Работает для большего количества ограничений и может быть легко сгенерирован, если некоторые ограничения должны быть включены / отключены конфигурацией.
узнал

2
Использование категорий Unicode - отличная идея. Мир шире ASCII!
Уолтер Тросс

1

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

@"^(?=.{8,}$)(?=[^A-Z]*[A-Z][^A-Z]*$)\w*\W\w*$"

Строка AAaaaaaaa#не соответствует этому выражению,
Кристиан Лупашку

3
Ну, это 10, а не 8 символов, и он содержит более одного верхнего регистра, поэтому он должен потерпеть неудачу ...
user1096188

4
Вы правы, это действительно говорить об этом в вопросе. Я думал, что эти правила больше похожи на «хотя бы один верхний регистр», а не «ровно на один верхний регистр» . Я не уверен, что OP хотел этого.
Cristian Lupascu


0

Этот вопрос становится вирусным, и появилось много интересных предложений.

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

Эти ссылки могут быть интересными: сопоставить хотя бы 2 цифры 2 буквы в любом порядке в строке , язык регулярных выражений , группы захвата

Я использую этот шаблон (?=(?:.*?({type})){({count})})на основе всего регулярного выражения, которое я видел в SO. Следующим шагом будет замена необходимого шаблона ( number, special character...) и добавление конфигурации длины.

Я сделал небольшой класс для составления регулярного выражения PasswordRegexGenerator.cs Пример:

string result = new PasswordRegexGenerator ( )
        .UpperCase ( 3, -1 )    // ... {3,}
        .Number ( 2, 4 )        // ... {2,4}
        .SpecialCharacter ( 2 ) // ... {2}
        .Total ( 8,-1 )
        .Compose ( );

/// <summary>
/// Generator for regular expression, validating password requirements.
/// </summary>
public class PasswordRegexGenerator
{
    private string _elementTemplate = "(?=(?:.*?({type})){({count})})";

    private Dictionary<string, string> _elements = new Dictionary<string, string> {
        { "uppercase", "[A-Z]" },
        { "lowercase", "[a-z]" },
        { "number", @"\d" },
        { "special", @"\W" },
        { "alphanumeric", @"\w" }
    };

    private StringBuilder _sb = new StringBuilder ( );

    private string Construct ( string what, int min, int max )
    {
        StringBuilder sb = new StringBuilder ( _elementTemplate );
        string count = min.ToString ( );

        if ( max == -1 )
        {
            count += ",";
        }
        else if ( max > 0 )
        {
            count += "," + max.ToString();
        }

        return sb
            .Replace ( "({type})", what )
            .Replace ( "({count})", count )
            .ToString ( );
    }

    /// <summary>
    /// Change the template for the generation of the regex parts
    /// </summary>
    /// <param name="newTemplate">the new template</param>
    /// <returns></returns>
    public PasswordRegexGenerator ChangeRegexTemplate ( string newTemplate )
    {
        _elementTemplate = newTemplate;
        return this;
       }

    /// <summary>
    /// Change or update the regex for a certain type ( number, uppercase ... )
    /// </summary>
    /// <param name="name">type of the regex</param>
    /// <param name="regex">new value for the regex</param>
    /// <returns></returns>
    public PasswordRegexGenerator ChangeRegexElements ( string name, string regex )
    {
        if ( _elements.ContainsKey ( name ) )
        {
            _elements[ name ] = regex;
        }
        else
        {
            _elements.Add ( name, regex );
        }
        return this;
    }

    #region construction methods 

    /// <summary>
    /// Adding number requirement
    /// </summary>
    /// <param name="min"></param>
    /// <param name="max"></param>
    /// <returns></returns>
    public PasswordRegexGenerator Number ( int min = 1, int max = 0 )
    {
        _sb.Append ( Construct ( _elements[ "number" ], min, max ) );
        return this;
    }

    public PasswordRegexGenerator UpperCase ( int min = 1, int max = 0 )
    {
        _sb.Append ( Construct ( _elements[ "uppercase" ], min, max ) );
        return this;
    }

    public PasswordRegexGenerator LowerCase ( int min = 1, int max = 0 )
    {
        _sb.Append ( Construct ( _elements[ "lowercase" ], min, max ) );
        return this;
    }

    public PasswordRegexGenerator SpecialCharacter ( int min = 1, int max = 0 )
    {
        _sb.Append ( Construct ( _elements[ "special" ], min, max ) );
        return this;
    }

    public PasswordRegexGenerator Total ( int min, int max = 0 )
    {
        string count = min.ToString ( ) + ( ( max == 0 ) ? "" : "," + max.ToString ( ) );
        _sb.Append ( ".{" + count + "}" );
        return this;
    }

    #endregion

    public string Compose ()
    {
        return "(" + _sb.ToString ( ) + ")";
    }
}

0

Вы можете использовать следующий класс для проверки:

public class PasswordValidator{

  private Pattern pattern;
  private Matcher matcher;

  private static final String PASSWORD_PATTERN =
          "((?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%]).{6,20})";

  public PasswordValidator(){
      pattern = Pattern.compile(PASSWORD_PATTERN);
  }

  /**
   * Validate password with regular expression
   * @param password password for validation
   * @return true valid password, false invalid password
   */
  public boolean validate(final String password){

      matcher = pattern.matcher(password);
      return matcher.matches();

  }
}

где 6 и 20 - минимальная и максимальная длина пароля.


0
  • Используйте выражение без обратного отслеживания, чтобы сначала сопоставить весь пароль, если он содержит не менее 8 символов (таким образом, не будет комбинаторного взрыва для длинных, но недействительных паролей): (?>{8,})
  • Используйте утверждения просмотра назад для проверки наличия всех требуемых символов (условия AND). (?<=...)
  • По крайней мере, один символ верхнего регистра: (?<=\p{Lu}.*)
  • По крайней мере, один специальный символ (немного двусмысленно, но давайте использовать не-слово): (?<=\W.*)
  • Как минимум один буквенно-цифровой символ (: (?<=\w.*)

Подвела:

(?>.{8,})(?<=\p{Lu}.*)(?<=\W.*)(?<=\w.*)


0

Best не использует регулярное выражение для всего. Эти требования очень легкие. В отношении ЦП строковые операции для проверки критериев / валидации намного дешевле и быстрее, чем регулярное выражение!


0

var regex =/^(?=.*\d)(?=.*[!@#$%^&*])(?=.*[a-z])(?=.*[A-Z]).{8,64}$/;

 
function test() {

 if(regex.test(document.getElementById("txtPassword").value)===false)
 {
 alert("Min 6,Max 64,At Least One Uppercase Character,One Lowercase Character,One Numeric Value And One Special Character(!@#$%^&*) Required ");
 }
 else
 {
 alert("Success");
 }
}
<input type="text" id="txtPassword" />
<button id="testBtn" onclick=test()>CheckPassword</button>


Хотя этот фрагмент кода может решить проблему, он не объясняет, почему и как он отвечает на вопрос. Пожалуйста, включите объяснение вашего кода , так как это действительно помогает улучшить качество вашего сообщения. Помните, что вы отвечаете на вопрос читателей в будущем, и эти люди могут не знать причины вашего предложения кода. Вы можете использовать кнопку редактирования , чтобы улучшить этот ответ, чтобы получить больше голосов и репутации!
Брайан Томпсетт - 汤 莱恩

-2
/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}$/

15
Я предлагаю вам отредактировать свой вопрос и включить некоторые пояснения. Ответы только с кодом иногда достаточно хороши, но ответы с кодом + объяснение всегда лучше
Барранка
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.