비밀번호가“대문자 1 개, 특수 문자 1 개, 영숫자 포함 8 자”인지 확인하는 정규식


102

정규 표현식을 사용하여

암호는 대문자 1 개, 특수 문자 1 개 및 영숫자를 포함하여 8 자 여야합니다.

그리고 여기에 대문자 1 개, 소문자 1 개, 숫자 또는 특수 문자 1 개를 포함하여 8 자에 대한 유효성 검사 표현식이 있습니다.

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

대문자 1 개, 특수 문자 1 개, 영숫자 문자를 포함하여 8 자 여야하는 비밀번호를 작성하려면 어떻게해야합니까?


26
이를 위해 정규 표현식이 필요한 이유는 무엇입니까? 요구 사항과 일치하는 완전한 정규 표현식은 매우 길고 복잡합니다. C # 코드로 제약 조건을 작성하는 것이 더 쉽습니다.
Greg Hewgill 2012

32
강력한 암호에 대한 불완전한 프록시 인 임의의 규칙을 암호가 충족하는지 확인하는 대신 강력한 암호 확인을 고려해 보셨습니까? 암호를 입력하면 강도를 결정하는 많은 라이브러리와 프로그램이 있습니다.
Wayne Conrad

4
@GregHewgill 내가 할 수 있다면 나는 당신의 코멘트를 찬성 할 것입니다 :-) 이것은 "당신이 가진 모든 것이 망치라면, 모든 것이 못처럼 보이기 시작한다"의 또 다른 경우처럼 보입니다.
Christian.K

3
정확히 하나의 대문자 / 특수 문자 가 필요 합니까 아니면 적어도 하나가 필요합니까?
mmdemirbas

4
사용자의 요구 사항에 따라 사용자가 구현 세부 사항을 지시하고 있음을 의미합니까? 아마도 그들은 이것을 스스로 코딩해야 할 것입니다. 솔직히 말해서 카운터를 만들고 모든 캐릭터를 하나씩 확인하고 규칙과 일치하는 모든 캐릭터에 대해 적절한 카운터를 증가 시키면 유지 관리하고 이해하는 것이 더 쉬울 것이라고 생각합니다. 기술적 인 관점에서 볼 때 누구에게도 깊은 인상을주지는 않지만 오류가 발생하기 쉽고 업데이트하기 어려운 것으로 복잡하게 만드는 이유는 무엇입니까?

답변:


132

당신이 추구하는 정규 표현식은 특히 정규 표현식에 익숙하지 않은 사람들을 위해 유지하기에는 거대하고 악몽 일 것입니다.

정규식을 분해하고 한 번에 하나씩 수행하는 것이 더 쉬울 것이라고 생각합니다. 더 많은 작업이 필요할 수 있지만 유지 관리 및 디버깅이 더 쉬울 것이라고 확신합니다. 이렇게하면 사용자에게보다 자세한 오류 메시지를 제공 할 수 Invalid Password있어 사용자 경험을 향상시킬 수 있습니다 ( 단지는 제외).

내가보기에 당신은 정규식에 꽤 유창하므로 필요한 일을하기 위해 정규식을 제공하는 것은 쓸모가 없을 것이라고 생각합니다.

귀하의 의견을 보면 다음과 같이 할 것입니다.

  • 8 자 여야합니다.이 경우 정규식이 필요하지 않습니다. .Length속성을 사용하면 충분합니다.

  • 대문자 1 개 포함 : [A-Z]+정규식을 사용할 수 있습니다 . 문자열에 하나 이상의 대문자가 포함 된 경우이 정규식은 true.

  • 하나의 특수 문자 : \W문자 나 숫자가 아닌 모든 문자와 일치하는를 사용할 수 있습니다. 그렇지 않으면 이와 같은 [!@#]것을 사용하여 특수 문자의 사용자 지정 목록을 지정할 수 있습니다 . 주 같은 그 자하지만 $, ^, (그리고 )그들과 같이 이스케이프 할 필요가 있으므로, 정규 표현식 언어의 특수 문자입니다 \$. 즉, \W.

  • 영숫자 :를 사용하면 \w+문자, 숫자 및 밑줄과 일치해야합니다.

자세한 내용 은 튜토리얼을 참조하십시오.


2
나는 구글 친애하는 친구에서 그것을 얻을이 내 자신 작성하지 않은
라니아 UMAIR

4
@RaniaUmair : 귀하의 의견이 내 요점을 증명한다고 생각합니다. 내가 지정한 것처럼 분해하는 것이 좋습니다.
npinti 2012

35
한 정규식은 강력하지만 우주의 모든 문제를 해결하기 위해 의미되지 않았다
크리스티안 루파 스쿠

@ w0lf : 더 이상 동의 할 수 없습니다. Regex는 강력하지만 너무 복잡해 지므로 간단하게 유지하는 것이 좋습니다.
npinti

당신이 나를 도울 수 난 아무것도 할 수있는 적어도 하나의 수와 최대 3 개 다른 많은 charecters을 수락 REGX 필요
Lijo

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

7
대신 {8}을 사용하여 8자를 일치시킬 수 있습니다
Angelo Tricarico

$ 1eerrrrrrr ..과 일치합니다. 대문자가 없습니다.
Shilpi Jaiswal

@ShilpiJaiswal 대소 문자를 구분하지 않는 일치에 플래그를 사용하거나 "일치"대신 "찾기"를 수행하고 있습니다. 전체 입력 문자열과 일치하는지 확인하기 위해 ^및 사이에 정규식을 묶을 수 있습니다 $. 이것을보십시오 :^((?=.*\d)(?=.*[A-Z])(?=.*\W).{8,8})$
mmdemirbas

35

너무 많은 답변 .... 모두 나쁘다!

정규식에는 AND 연산자가 없으므로 유효성이 무언가와 다른 무언가에 의해 정의 될 때 유효한 암호와 일치하는 정규식을 작성하기가 매우 어렵습니다.

그러나, 정규 표현식 , 그래서 그냥 드 모르 강의 법칙을 적용하고, 일치하는 정규식 쓰기는 OR 연산자가 잘못된 암호를.

8 자 미만 무엇이든 또는 어떤 번호가 무엇이든 또는 어떤 대문자 아무것도 또는 특수 문자 아무것도

그래서:

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

일치하는 것이 있으면 잘못된 암호입니다.


3
OP가 정확히 8자를 원하면 |.{9,}. +1 개념
Daniel

질문에 대한 위대하고 간단한 해결책이지만 단일 정규식이 실제 문제에 대한 최적의 표현이 아니라는 데 동의합니다.
Siderite Zackwehdex

1
정규식 에는 AND 연산자 있으며이를 미리보기 / 예상 비하인드 어설 션이라고합니다.
relatively_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 또는 유니 코드입니까? 질문을 읽은 내 추측은 적어도 하나의 소문자가 가정된다는 것입니다. 따라서 가정 된 마지막 규칙은 다음과 같아야한다고 생각합니다.

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

(보안 중심으로 변경하는 것은 정말 성가 시거나 유용하지 않은 규칙입니다.)

질문이 틀렸을 때 아는 것을 배우는 것이 영리한 답변보다 훨씬 더 중요합니다. 잘못된 질문에 대한 영리한 대답은 거의 항상 잘못되었습니다.


2
나는 동의한다. 더 많은 사람들과 함께 일할수록 더 많은 코드를 읽을 수 있어야합니다. 일부 정규 표현식 구현은 대답이 매우 명확합니다.
Nicola Peluchetti 2015 년

저는 여러분과 같은 일부 사용자가 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 종류의 "and"패턴 을 남용하는 가장 좋은 방법 입니다. 더 많은 제약 조건에 대해 작동하며 일부 제약 조건이 구성에 의해 활성화 / 비활성화되어야하는 경우 쉽게 생성 할 수 있습니다.
dognose 2015 년

2
유니 코드 범주 의 사용은 훌륭한 아이디어입니다. 세상은 ASCII보다 더 넓습니다!
Walter Tross

1

대문자와 특수 문자가 하나만 필요한 경우 다음이 작동합니다.

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

문자열 AAaaaaaaa#이 표현에 따라 확인을하지 않습니다
크리스티안 루파 스쿠

3
음 ..., 안 8 자, 10이며이 실패 할 수 있도록, 하나 이상의 대문자 후자 포함
user1096188

4
당신은, 맞다 않는 질문이 말한다. 나는이 규칙이 "정확히 하나대문자" 대신 "적어도 하나의 대문자"에 더 가깝다고 생각했습니다 . 나는 그것이 OP가 원했던 것인지 잘 모르겠습니다.
Cristian Lupascu 2012


0

이 질문은 바이러스 성으로 시작되고 많은 흥미로운 제안이 나타났습니다.

네, 손으로 쓰는 것은 어렵습니다. 따라서 더 쉬운 해결책은 템플릿을 사용하는 것입니다. 결과 정규식이 최적이 아닐 수 있지만 유지 관리 및 / 또는 변경이 더 쉬우 며 사용자가 결과를 더 잘 제어 할 수 있습니다. 내가 뭔가를 놓쳤을 가능성이 있으므로 건설적인 비판이 도움이 될 것입니다.

이 링크는 흥미로울 수 있습니다. 문자열에서 순서에 관계없이 최소 2 자리 2 문자 일치 , 정규식 언어 , 그룹 캡처

나는 내가 본 (?=(?:.*?({type})){({count})})모든 정규식을 기반 으로이 템플릿을 사용하고 있습니다. 다음 단계는 필요한 패턴 ( 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 조건)가 있는지 확인하려면 lookbehind 어설 션을 사용하십시오. (?<=...)
  • 적어도 하나의 대문자: (?<=\p{Lu}.*)
  • 하나 이상의 특수 문자 (조금 모호하지만 단어가 아닌 것을 사용합시다) : (?<=\W.*)
  • 하나 이상의 영숫자 (: (?<=\w.*)

요약 :

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


0

최고는 모든 것에 정규식을 사용하지 않는 것입니다. 이러한 요구 사항은 매우 가볍습니다. 기준 / 유효성 검사를위한 CPU 현명한 문자열 작업에서 정규식보다 훨씬 저렴하고 빠릅니다!


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

15
질문을 수정하고 몇 가지 설명을 포함하는 것이 좋습니다. 코드 전용 답변 때로는 충분하지만, 코드 + 설명의 대답은 더 나은 항상
Barranka
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.