diff --git a/src/main/java/com/eactive/apim/portal/apps/user/dto/PortalUserRegistrationDTO.java b/src/main/java/com/eactive/apim/portal/apps/user/dto/PortalUserRegistrationDTO.java index b12a450..cf41d11 100644 --- a/src/main/java/com/eactive/apim/portal/apps/user/dto/PortalUserRegistrationDTO.java +++ b/src/main/java/com/eactive/apim/portal/apps/user/dto/PortalUserRegistrationDTO.java @@ -3,8 +3,7 @@ package com.eactive.apim.portal.apps.user.dto; import com.eactive.apim.portal.common.validator.AuthNumberMatch; import com.eactive.apim.portal.common.validator.CellPhone; import com.eactive.apim.portal.common.validator.PasswordMatch; -import com.eactive.apim.portal.common.validator.PasswordRule; -import com.eactive.apim.portal.common.validator.PasswordRuleForKbank; +import com.eactive.apim.portal.common.validator.PasswordRuleForKjbank; import lombok.Data; import org.hibernate.validator.constraints.Length; import org.hibernate.validator.constraints.NotEmpty; @@ -13,7 +12,7 @@ import org.hibernate.validator.constraints.NotEmpty; @AuthNumberMatch(recipient = "loginId", authField = "authNumber") @PasswordMatch(input = "password", confirm = "password2") @Data -@PasswordRuleForKbank(password = "password", loginId = "loginId", mobile = "mobileNumber") +@PasswordRuleForKjbank(password = "password", loginId = "loginId", mobile = "mobileNumber") public class PortalUserRegistrationDTO { /** diff --git a/src/main/java/com/eactive/apim/portal/apps/user/dto/UserRegisterDTO.java b/src/main/java/com/eactive/apim/portal/apps/user/dto/UserRegisterDTO.java index 7340660..c200c9b 100644 --- a/src/main/java/com/eactive/apim/portal/apps/user/dto/UserRegisterDTO.java +++ b/src/main/java/com/eactive/apim/portal/apps/user/dto/UserRegisterDTO.java @@ -1,8 +1,7 @@ package com.eactive.apim.portal.apps.user.dto; import com.eactive.apim.portal.common.validator.PasswordMatch; -import com.eactive.apim.portal.common.validator.PasswordRule; -import com.eactive.apim.portal.common.validator.PasswordRuleForKbank; +import com.eactive.apim.portal.common.validator.PasswordRuleForKjbank; import com.eactive.apim.portal.common.validator.UniqueId; import com.eactive.apim.portal.portaluser.entity.UserStatus; import lombok.Data; @@ -14,7 +13,7 @@ import java.io.Serializable; @PasswordMatch(input = "password", confirm = "password2") @Data -@PasswordRuleForKbank(loginId = "userId", password = "password", mobile = "mobilePhone") +@PasswordRuleForKjbank(loginId = "userId", password = "password", mobile = "mobilePhone") public class UserRegisterDTO implements Serializable { diff --git a/src/main/java/com/eactive/apim/portal/apps/user/validator/PasswordValidator.java b/src/main/java/com/eactive/apim/portal/apps/user/validator/PasswordValidator.java index c670202..6ca9f6b 100644 --- a/src/main/java/com/eactive/apim/portal/apps/user/validator/PasswordValidator.java +++ b/src/main/java/com/eactive/apim/portal/apps/user/validator/PasswordValidator.java @@ -1,6 +1,7 @@ package com.eactive.apim.portal.apps.user.validator; import com.eactive.apim.portal.common.validator.PasswordRuleForKbankValidator; +import com.eactive.apim.portal.common.validator.PasswordRuleForKjbankValidator; import org.springframework.stereotype.Component; @Component @@ -16,7 +17,7 @@ public class PasswordValidator { } public boolean isValidPassword(String password, String loginId, String mobileNumber) { - PasswordRuleForKbankValidator validator = new PasswordRuleForKbankValidator(); + PasswordRuleForKjbankValidator validator = new PasswordRuleForKjbankValidator(); return validator.isValid(password, loginId, mobileNumber); } diff --git a/src/main/java/com/eactive/apim/portal/common/user/PortalAuthenticatedUser.java b/src/main/java/com/eactive/apim/portal/common/user/PortalAuthenticatedUser.java index 251d1d2..6d8f3e0 100644 --- a/src/main/java/com/eactive/apim/portal/common/user/PortalAuthenticatedUser.java +++ b/src/main/java/com/eactive/apim/portal/common/user/PortalAuthenticatedUser.java @@ -40,7 +40,7 @@ public class PortalAuthenticatedUser extends PortalUser implements UserDetails { @Override public boolean isAccountNonLocked() { - return true; + return !"Y".equalsIgnoreCase(this.getAccountLockYn()); } @Override diff --git a/src/main/java/com/eactive/apim/portal/common/validator/PasswordRuleForKjbank.java b/src/main/java/com/eactive/apim/portal/common/validator/PasswordRuleForKjbank.java new file mode 100644 index 0000000..dab49ad --- /dev/null +++ b/src/main/java/com/eactive/apim/portal/common/validator/PasswordRuleForKjbank.java @@ -0,0 +1,24 @@ +package com.eactive.apim.portal.common.validator; + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.*; + +@Constraint(validatedBy = PasswordRuleForKjbankValidator.class) +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface PasswordRuleForKjbank { + String message() default "비밀 번호 규칙에 부합하지 않습니다.(영문/숫자/특수문자 포함 8~20자, 아이디, 휴대전화, 3자리 이상 연속,반복 문자 불가)"; + + Class[] groups() default {}; + + Class[] payload() default {}; + + String password(); + + String loginId(); + + String mobile(); + +} diff --git a/src/main/java/com/eactive/apim/portal/common/validator/PasswordRuleForKjbankValidator.java b/src/main/java/com/eactive/apim/portal/common/validator/PasswordRuleForKjbankValidator.java new file mode 100644 index 0000000..35d7201 --- /dev/null +++ b/src/main/java/com/eactive/apim/portal/common/validator/PasswordRuleForKjbankValidator.java @@ -0,0 +1,144 @@ +package com.eactive.apim.portal.common.validator; + +import org.apache.commons.beanutils.PropertyUtils; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Created by Sungpil Hyun + */ +public class PasswordRuleForKjbankValidator implements ConstraintValidator { + + // 최소 8자, 최대 20자 상수 선언 + private static final int MIN = 8; + private static final int MAX = 20; + + private String password; + private String loginId; + private String mobileNumber; + + // 3자리 연속 문자 정규식 + private static final String SAMEPT = "(\\w)\\1\\1"; + // 공백 문자 정규식 + private static final String BLANKPT = "(\\s)"; + + @Override + public void initialize(PasswordRuleForKjbank constraintAnnotation) { + this.password = constraintAnnotation.password(); + this.loginId = constraintAnnotation.loginId(); + this.mobileNumber = constraintAnnotation.mobile(); + } + + @Override + public boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) { + + String passwordValue = null; + String loginIdValue = null; + String mobileNumberValue = null; + + try { + passwordValue = (String) PropertyUtils.getProperty(value, this.password); + loginIdValue = (String) PropertyUtils.getProperty(value, this.loginId); + mobileNumberValue = (String) PropertyUtils.getProperty(value, this.mobileNumber); + } catch (Exception e) { + return false; + } + + return isValid(passwordValue, loginIdValue, mobileNumberValue); + } + + public boolean isValid(String password, String loginId, String mobileNumber) { + // 영어, 숫자, 특수문자 포함한 MIN to MAX 글자 정규식 + String REGEX = "^((?=.*\\d)(?=.*[a-zA-Z])(?=.*[\\W]).{" + MIN + "," + MAX + "})$"; + + // 정규식 검사객체 + Matcher matcher; + + // 공백 체크 + if (password == null || "".equals(password)) { + return false; + } + + // ASCII 문자 비교를 위한 UpperCase + String tmpPw = password.toUpperCase(); + // 문자열 길이 + int strLen = tmpPw.length(); + + // 글자 길이 체크 + if (strLen > 20 || strLen < 8) { + return false; + } + + if (loginId != null && !loginId.isEmpty()) { + String[] loginParts = loginId.split("@"); + if (loginParts.length > 0) { + String username = loginParts[0].toUpperCase(); + if (tmpPw.contains(username)) { + return false; + } + } + } + + // Mobile number validation + if (mobileNumber != null && !mobileNumber.isEmpty()) { + String[] mobileParts = mobileNumber.split("-"); + for (String part : mobileParts) { + if (!part.isEmpty() && tmpPw.contains(part)) { + return false; + } + } + } + + // 공백 체크 + matcher = Pattern.compile(BLANKPT).matcher(tmpPw); + if (matcher.find()) { + return false; + } + + // 비밀번호 정규식 체크 + matcher = Pattern.compile(REGEX).matcher(tmpPw); + if (!matcher.find()) { + return false; + } + + // 동일한 문자 3개 이상 체크 + matcher = Pattern.compile(SAMEPT).matcher(tmpPw); + if (matcher.find()) { + return false; + } + + // 연속된 문자 / 숫자 3개 이상 체크 + // ASCII Char를 담을 배열 선언 + int[] tmpArray = new int[strLen]; + + // Make Array + for (int i = 0; i < strLen; i++) { + tmpArray[i] = tmpPw.charAt(i); + } + + // Validation Array + for (int i = 0; i < strLen - 2; i++) { + if (isContinuous(tmpArray[i], tmpArray[i + 2]) && isContinuous(tmpArray[i], tmpArray[i + 1], tmpArray[i + 2])) { + return false; + } + } + // Validation Complete + return true; + } + + + + static boolean isContinuous(int first, int third) { + // 첫 글자 A-Z / 0-9 + return (first > 47 && third < 58) || (first > 64 && third < 91); + } + + static boolean isContinuous(int first, int second, int third) { + // 배열의 연속된 수 검사 + // 3번째 글자 - 2번째 글자 = 1, 3번째 글자 - 1번째 글자 = 2 + return Math.abs(third - second) == 1 && Math.abs(third - first) == 2; + } +}