[java] 암호 유효성 검사를위한 Regexp Java
Java 응용 프로그램에서 구성 매개 변수로 사용할 암호 유효성 검사를위한 정규 표현식을 만들고 있습니다.
정규식은 다음과 같습니다.
^.*(?=.{8,})(?=..*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).*$
비밀번호 정책은 다음과 같습니다.
-
8 자 이상
-
하나 이상의 숫자를 포함합니다.
-
하나 이상의 하위 알파 문자와 하나의 상위 알파 문자를 포함합니다.
-
특수 문자 집합 (
@#%$^
등) 내에 하나 이상의 문자를 포함합니다 . -
공백, 탭 등을 포함하지 않습니다.
포인트 5 만 누락되었습니다. 정규 표현식에서 공백, 탭, 캐리지 리턴 등을 확인할 수 없습니다.
누구든지 나를 도울 수 있습니까?
답변
이 시도:
^(?=.*[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 는 .NET과 독립적으로 전체 문자열의 유효성을 검사하기 위해 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
점은 실제로 어떤 문자를 허용하려는 경우에만 사용해야합니다. 그렇지 않으면 (부정 된) 문자 클래스를 사용하여 정규식을 실제로 허용되는 문자로만 제한하십시오. 이 경우에는 별 차이가 없지만 다른 것이 더 적절할 때 점을 사용하지 않는 것은 아주 좋은 습관입니다. 개발자가 점보다 더 적절한 것을 사용하기에는 너무 게으 르기 때문에 엄청난 역 추적 사례가 너무 많습니다 .
초기 테스트에서 암호의 전반부에서 적절한 문자를 찾을 가능성이 높기 때문에 lazy quantifier가 더 효율적일 수 있습니다.
\A(?=\S*?[0-9])(?=\S*?[a-z])(?=\S*?[A-Z])(?=\S*?[@#$%^&+=])\S{8,}\z
그러나 이제 정말 중요한 문제에 대해 설명합니다. 원래 질문이 ASCII로 생각하는 사람이 작성한 것처럼 보인다는 사실에 대한 답변은 없습니다. 그러나 Java에서 문자열은 유니 코드입니다. 비 ASCII 문자가 비밀번호에 허용됩니까? 그럴 경우 ASCII 공백 만 허용되거나 모든 유니 코드 공백을 제외해야합니다.
기본적으로 \s
ASCII 공백 만 일치하므로 그 역 \S
은 모든 유니 코드 문자 (공백 여부) 및 모든 비 공백 ASCII 문자와 일치합니다. 유니 코드 문자는 허용되지만 유니 코드 공백은 허용되지 않는 경우 유니 코드 공백 UNICODE_CHARACTER_CLASS
을 \S
제외 하도록 플래그를 지정할 수 있습니다 . 유니 코드 문자가 허용 되지 않으면 공백이나 제어 문자가 아닌 모든 ASCII 문자를 일치시키는 [\x21-\x7E]
대신 사용할 수 있습니다 \S
.
다음으로 잠재적 인 문제가 있습니다. 제어 문자를 허용 하시겠습니까? 적절한 정규식을 작성하는 첫 번째 단계는 일치하려는 항목과 일치하지 않는 항목을 정확하게 지정하는 것입니다. 기술적으로 유일한 100 % 정답은 제어 문자 또는 비 ASCII 문자와 같은 특정 범위의 문자가 허용되는지 여부를 나타내지 않기 때문에 질문의 암호 사양이 모호하다는 것입니다.
답변
지나치게 복잡한 Regex (피할 수있는 경우)를 사용해서는 안됩니다.
- 읽기 어렵다 (적어도 자신을 제외한 모든 사람에게)
- 확장하기 어렵다
- 디버그하기 어렵다
작은 정규식을 많이 사용하는 데 약간의 성능 오버 헤드가있을 수 있지만 위의 점은 쉽게 가중치를 초과합니다.
다음과 같이 구현합니다.
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;
}
답변
암호 요구 사항 :
- 암호는 시스템에서 지원할 수있는 8 자 이상이어야합니다.
-
비밀번호에는 알파벳, 숫자 및 특수 문자와 같은 그룹 중 최소 2 개 이상의 문자가 포함되어야합니다.
^.*(?=.{8,})(?=.*\d)(?=.*[a-zA-Z])|(?=.{8,})(?=.*\d)(?=.*[!@#$%^&])|(?=.{8,})(?=.*[a-zA-Z])(?=.*[!@#$%^&]).*$
나는 그것을 테스트하고 작동합니다.
답변
각 유형의 캐릭터에 대한 최소 요구 사항에 관심이있는 사람에게는 Tomalak의 허용 된 답변에 대해 다음 확장을 제안합니다.
^(?=(.*[0-9]){%d,})(?=(.*[a-z]){%d,})(?=(.*[A-Z]){%d,})(?=(.*[^0-9a-zA-Z]){%d,})(?=\S+$).{%d,}$
이것은 최종 정규식 패턴이 아니라 형식화 문자열입니다. 숫자, 소문자, 대문자, 숫자 / 문자가 아닌 문자 및 전체 암호 (각각)에 대해 필요한 최소 항목으로 % d를 대체하십시오. 최대 발생 가능성은 거의 없지만 (최대 0을 원하지 않는 한 이러한 문자를 효과적으로 거부하지 않는 한) 쉽게 추가 할 수 있습니다. 최소 / 최대 제약 조건이 비 연속적인 일치를 허용하도록 각 유형 주변의 추가 그룹화에 유의하십시오. 이것은 우리가 필요한 각 유형의 문자 수를 중앙에서 구성한 다음 위의 형식 지정 문자열을 기반으로 정규식 패턴을 구성하기 위해 해당 정보를 가져 오는 두 개의 서로 다른 모바일 플랫폼과 웹 사이트를 구성 할 수있는 시스템에서 놀라운 일이었습니다.
답변
이것은 모든 특수 문자를 확인합니다.
^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=\S+$).*[A-Za-z0-9].{8,}$