비밀번호 정책이 변경 되어 로직을 수정해야하는 업무를 받았다.
이번 리팩토링에서는 MAP을 활용하고, 테스트케이스를 만들어 간단한 테스트를 진행하였다.
(변경 전) '대문자, 소문자, 특수문자, 숫자' 중 4가지를 모두 포함
(변경 후) '대문자, 소문자, 특수문자, 숫자' 중 최소 3가지를 포함
기존 로직을 살펴보면, 서버에서 설정을 받아와 해당하는 유효성 검사 타입에 따라
정규식에 더한 이후, 한 번에 유효성 검사를 확인하는 것을 확인할 수 있다.
package refactoring3;
import java.util.regex.Pattern;
public class PasswordUtil {
public static boolean checkValidPassword(String newPassword) {
boolean result = true;
// 서버설정으로부터 비밀번호 정책 받아오기
// ...
// 패스워드 정책
String pwdCValidType = "U,L,S,N";
String pwdMinLength = "8";
String pwdMaxLength = "20";
// 비밀번호 길이 체크 로직
// if (짧거나 길다면) return false;
// 정규표현식 생성
String regExpStrMust = "^";
// 비밀번호 정책 배열 생성
String[] validType = pwdCValidType.split(",");
for(int i =0; i < validType.length; i++){
switch (validType[i]){
case "U" : // 대문자
regExpStrMust += "(?=.*[A-Z])";
break;
case "L" : // 소문자
regExpStrMust += "(?=.*[a-z])";
break;
case "S" : // 특수문자
regExpStrMust += "(?=.*[~!@#$%^&*+=_{}:;'\"<>,./()|-])";
break;
case "N" : // 숫자
regExpStrMust += "(?=.*[0-9])";
break;
}
}
// 비멀번호 유효성 검사
if(Pattern.compile(regExpStrMust).matcher(newPassword).find()){
return true;
} else {
return false;
}
}
}
기존 로직을 사용할 경우, 최소 3가지
라는 개념을 적용할 수 없어 변경이 필요했다.
MAP으로 정규표현식을 담아준 후, 해당하는 서버 설정에 따라 유효성 검사를 진행하며
끝으로 해당 유효성 검사가 충족되었는지를 판단한다.
package refactoring3;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
public class refactoredPasswordUtil {
public static boolean checkValidPassword(String newPassword) {
boolean result = true;
// 서버설정으로부터 비밀번호 정책 받아오기
// ...
// 패스워드 정책
String pwdCValidType = "3,U,L,S,N";
String pwdMinLength = "8";
String pwdMaxLength = "20";
// 비밀번호 길이 체크 로직
// if (짧거나 길다면) return false;
// 정규표현식
String upperRegex = "(?=.*[A-Z])"; // 대문자
String smallRegex = ".(?=.*[a-z])"; // 소문자
String specialRegex = "(?=.*[~!@#$%^&*+=_{}:;'\"<>,./()|-])"; // 특수문자
String numberRegex = "(?=.*[0-9])"; // 숫자
// 정규표현식 MAP 생성
Map<String, Pattern> checkValidType = new HashMap<>();
checkValidType.put("U", Pattern.compile(upperRegex));
checkValidType.put("L", Pattern.compile(smallRegex));
checkValidType.put("S", Pattern.compile(specialRegex));
checkValidType.put("N", Pattern.compile(numberRegex));
// 비밀번호 정책 배열 생성
String[] validType = pwdCValidType.split(",");
// 비밀번호 검사를 위한 int값 생성
int requiredCount = Integer.parseInt(validType[0]);
int satisfiedCount = 0;
// 비멀번호 유효성 검사
for (String valid : validType){
if (isNumeric(valid)) continue;
Pattern checkRegex = checkValidType.get(valid);
if (checkRegex.matcher(newPassword).find()) satisfiedCount++;
}
// 검사한 비밀번호 유효성 수가 부족하다면 false return
return satisfiedCount >= requiredCount;
}
public static boolean isNumeric(String str) {
return str.chars().allMatch(Character::isDigit);
}
}
내가 작성한 코드가 문제 없이 작동하는지 확인이 필요했다.
간단하게 테스트 코드를 작성하였다.
ChatGPT의 도움을 빌려 테스트 케이스를 받았고, 테스트 결과 모든 케이스를 통과하는 것을 확인할 수 있었다.
package refactoring3;
public class testPasswordUtil {
public static void main(String[] args) {
// 유효한 비밀번호 (대문자, 소문자, 특수문자, 숫자 중 3가지 포함)
String[] validPasswords = {
"ValidPassword1!", // 대문자, 소문자, 숫자 포함
"PaSsWoRd123@", // 대문자, 소문자, 특수문자 포함
"SecurePwd!2022", // 대문자, 특수문자, 숫자 포함
"9StrongPwd!", // 소문자, 특수문자, 숫자 포함
"Passw0rd!!2024", // 대문자, 소문자, 특수문자 포함
"My$ecurePwd11", // 대문자, 특수문자, 숫자 포함
"Pwd!9876My", // 대문자, 특수문자, 숫자 포함
"V@lidP@ssw0rd" // 대문자, 소문자, 특수문자 포함
};
// 유효하지 않은 비밀번호
String[] invalidPasswords = {
"NoNumbers", // 특수문자, 숫자 없음
"nouppercaseor123", // 특수문자, 대문자 없음
"SPECIAL123123", // 특수문자, 소문자 없음
"12@3456789", // 대문자, 소문 없음
"onlylower@caseletters", // 대문자, 숫자 없음
"abcd1234567", // 대문자, 특수문자 없음
"ACD213456", // 소문자, 특수문자 없음
"ABCD@#!@%$", // 소문자, 숫자 없음
"AacDfdfasd" // 특수문자, 숫자 없음
};
for (String test : validPasswords){
if(refactoredPasswordUtil.checkValidPassword(test)){
System.out.println("테스트 통과");
} else {
System.out.println("테스트 실패" + test);
}
}
System.out.println("=================");
for (String test : invalidPasswords){
if (refactoredPasswordUtil.checkValidPassword(test)){
System.out.println("테스트 실패" + test);
} else {
System.out.println("테스트 통과");
}
}
}
}
테스트 통과
테스트 통과
테스트 통과
테스트 통과
테스트 통과
테스트 통과
테스트 통과
테스트 통과
=================
테스트 통과
테스트 통과
테스트 통과
테스트 통과
테스트 통과
테스트 통과
테스트 통과
테스트 통과
테스트 통과