본문 바로가기
dev/javascript

[javascript] 자바스크립트 정규표현식 비밀번호 강도 확인

by 최연탄 2023. 3. 21.
728x90
반응형

참고: https://www.section.io/engineering-education/password-strength-checker-javascript/

비밀번호는 애플리케이션 보안에서 매우 중요합니다. 누구나 자신의 시스템과 계정을 보호하기 위해 강력한 암호가 필요합니다. 이 포스트에서는 최종 사용자가 JavaScript의 정규식을 사용하여 계정을 보호할 수 있을 만큼 강력한 암호를 선택했는지 확인하는 방법에 대해 설명 하겠습니다.

정규표현식

정규식은 문자열의 문자 조합을 매치하는 데 사용하는 패턴입니다. JavaScript에서 정규식은 객체이기도 하고 RegExp로도 표시합니다. 이는 다음과 같이 구성할 수 있습니다:

- 패턴을 두개의 슬래시로 묶은 정규식 리터럴

let check = /vet/

- RegExp() 클래스의 생성자를 통해 확인할 문자열 전달

let check = new RegExp('vet');

패턴이 계속 변경되거나 패턴을 사용자의 입력에서 가져올 경우 생성자 함수를 사용합니다. 이번에는 사용자로부터 비밀번호를 얻을 것이므로 생성자 기능을 사용하겠습니다.

Patterns

패턴 의미
\d 숫자가 일치하는지 확인(예: "U2"에서 2 리턴)
\W 특수문자 확인(예: "2%"에서 % 리턴)
x{n,} n개 이상의 매치가 있는지 확인, "O{2,}"일 경우 "BOY"는 아무 것도 리턴하지 않지만 "GOOOAL"은 모든 O 리턴
x|y 문자열에 x 또는 y가 있는지 확인
[^vet] 부정 집합, 범위에 포함된 값을 제외하고 매치, "veterinary"에서 vet을 제외하고 매치
[A-Za-z0-9] 모든 알파벳과 숫자 확인
[a-z] 모든 소문자 확인
[A-Z] 모든 대문자 확인
x(?=y) 뒤에 y가 올 때만 x 리턴
. 줄 끝을 제외한 모든 단일 문자 확인
x* x가 0개 이상 있는지 확인

비밀번호 강도 확인을 위한 정규표현식

다음 규칙에 따라 사용자가 입력하는 비밀번호의 강도를 확인합니다.

  • 비밀번호가 최소 8 자리 이상 (?=.{8,))
  • 비밀번호에 한개 이상의 대문자 포함 (?=.*[A-Z])
  • 비밀번호에 한개 이상의 소문자 포함 (?=.*[a-z])
  • 비밀번호에 최소 하나의 숫자 포함 (?=.*[0-9])
  • 특수문자 하나 이상 포함 ([^A-Za-z0-9])

비밀번호가 얼마나 안전한지를 나타내는 세 가지 수준이 있습니다.

1. Strong: 비밀번호가 모든 요구 사항을 충족할 때

위의 조건에 따라 최소 하나 이상의 소문자, 하나의 대문자, 하나의 숫자, 하나의 특수문자, 최소 8 자리 입니다.

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

2. Medium: 비밀번호 6 자리 이상, 모든 요구 사항을 충족하거나 숫자만 빼고 나머지를 충족하는 경우

코드는 6자리를 체크하기 위해 마지막 (?=.{6,})만 빼고 Strong과 같게 만든 다음 | 을 추가하여 둘 중의 하나의 조건에 매치하도록 합니다.

((?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[^A-Za-z0-9])(?=.{6,}))|((?=.*[a-z])(?=.*[A-Z])(?=.*[^A-Za-z0-9])(?=.{8,}))

3. Weak: 입력한 비밀번호가 strong 이나 medium을 만족하지 못한 경우

HTML 코드

<html>

<head>
  <!-- Bootstrap 5 link -->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet"
    integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous">
  <style>
    .displayBadge {
      display: none;
      text-align: center;
    }
  </style>
</head>

<body>
  <div class="d-flex flex-column align-items-center">
    <h4 class="d-flex justify-content-center my-3">
      Password Strength Checker
    </h4>
    <input type="password" placeholder="Type your password" id="PassEntry" class="form-control text-center my-3">
    <span id="StrengthDisp" class="badge displayBadge my-3"></span>
  </div>

  <script src="script.js"></script>
</body>

</html>
  • Bootstrap stylesheet의 CDN 경로를 <link> 태크를 통해 HTML 파일에 연결하여 Bootstrap 5를 사용합니다.
  • <style> 태그를 통해 커스텀 스타일을 적용할 것 입니다. 비밀번호 강도 표시는 사용자가 비밀번호를 입력했을 때만 표시할 것 이므로 displayBadge 클래스는 숨기도록 하겠습니다.
  • <body> 태그에는 <div>와 함께 세 개의 자식 요소를 가집니다.
  • 첫 번째 요소는 제목 표시를 위해 간단히 h4를 사용합니다.
  • 두 번째 요소는 <input>으로 비밀번호를 입력할 곳 입니다.
  • 세 번째 요소는 <span>으로 비밀번호 강도를 표시할 부분입니다. (강력한 경우 초록색, 중간의 경우 파란색, 약한 경우 빨간색)

JavaScript 코드

먼저 다섯 개의 변수를 만듭니다.

  1. timeout: 콜백이 호출되기 전 timeout id 저장
  2. password: 입력된 비밀번호 저장
  3. strengthBadge: 비밀번호의 강도를 표시하는 부분
  4. strongPassword: strong 정규표현식을 저장
  5. mediumPassword: medium 정규표현식을 저장
let timeout;
let password = document.getElementById('PassEntry');
let strengthBadge = document.getElementById('StrengthDisp');
let strongPassword = new RegExp('(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[^A-Za-z0-9])(?=.{8,})')
let mediumPassword = new RegExp('((?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[^A-Za-z0-9])(?=.{6,}))|((?=.*[a-z])(?=.*[A-Z])(?=.*[^A-Za-z0-9])(?=.{8,}))')

정규식을 RegExp.prototype.test() 메소드로 테스트하여 암호의 강도를 확인하는 StrengthChecker라는 함수를 만들어 보겠습니다. 일치하는 항목이 있으면 true를 리턴하고 일치하는 항목이 없으면 false를 리턴합니다.

그 다음 함수의 결과에 따라 뱃지의 배경색(strengthBadge.style.backgroundColor)과 텍스트(strengthBadge.textContent)를 설정합니다.

function StrengthChecker(PasswordParameter) {
  if (strongPassword.test(PasswordParameter)) {
    strengthBadge.style.backgroundColor = "green"
    strengthBadge.textContent = 'Strong'
  } else if (mediumPassword.test(PasswordParameter)) {
    strengthBadge.style.backgroundColor = 'blue'
    strengthBadge.textContent = 'Medium'
  } else {
    strengthBadge.style.backgroundColor = 'red'
    strengthBadge.textContent = 'Weak'
  }
}

이벤트 리스너를 비밀번호 input에 추가하고 사용자가 무언가를 입력했을 때 StrengthChecker 함수로 강도를 확인해 보겠습니다. 여기서 키를 누를 때마다 바로 함수를 호출하지 않을 것 입니다. 입력이 있을 때 마다 정규식을 확인하지 않고 사용자가 빠르게 입력하다 멈췄을 때 강도를 체크하기 위해 타임아웃을 설정할 것입니다.

이전 타임아웃이 있으면 취소해야 합니다. 이벤트가 타임아웃 시간보다 더 빨리 발생하면 이전 입력 이벤트의 타임아웃을 취소해야 합니다.

password.addEventListener("input", () => {
  strengthBadge.style.display = 'block'

  clearTimeout(timeout);

  timeout = setTimeout(() => StrengthChecker(password.value), 100);

  if (password.value.length !== 0) {
    strengthBadge.style.display != 'block'
  } else {
    strengthBadge.style.display = 'none'
  }
});

전체 코드

See the Pen Password Strength Checker by shinyks (@shinyks) on CodePen.

정리

JavaScript의 정규식을 사용하여 3단계 암호 검사기를 만드는 방법을 알아봤습니다. Too Strong 및 Too Weak와 같은 더 많은 레벨을 구현하여 예제를 만들 수 있습니다.

JavaScript의 정규표현식에 대해 더 알고 싶으면 MDN 문서를 확인하기 바랍니다.

관련 글

자바스크립트 정규식으로 이메일 검증

반응형

댓글