diff --git a/src/main/java/com/kamco/cd/kamcoback/auth/CustomAuthenticationProvider.java b/src/main/java/com/kamco/cd/kamcoback/auth/CustomAuthenticationProvider.java index 98601d76..333b673a 100644 --- a/src/main/java/com/kamco/cd/kamcoback/auth/CustomAuthenticationProvider.java +++ b/src/main/java/com/kamco/cd/kamcoback/auth/CustomAuthenticationProvider.java @@ -32,7 +32,7 @@ public class CustomAuthenticationProvider implements AuthenticationProvider { // 미사용 상태 if (member.getStatus().equals(StatusType.INACTIVE.getId())) { - throw new CustomApiException(AuthErrorCode.LOGIN_ID_NOT_FOUND); + throw new CustomApiException(AuthErrorCode.INACTIVE_ID); } // jBCrypt + 커스텀 salt 로 저장된 패스워드 비교 diff --git a/src/main/java/com/kamco/cd/kamcoback/common/enums/error/AuthErrorCode.java b/src/main/java/com/kamco/cd/kamcoback/common/enums/error/AuthErrorCode.java index 4f5f45dd..ad3fcc76 100644 --- a/src/main/java/com/kamco/cd/kamcoback/common/enums/error/AuthErrorCode.java +++ b/src/main/java/com/kamco/cd/kamcoback/common/enums/error/AuthErrorCode.java @@ -10,7 +10,9 @@ public enum AuthErrorCode implements ErrorCode { LOGIN_PASSWORD_MISMATCH("LOGIN_PASSWORD_MISMATCH", HttpStatus.UNAUTHORIZED), - LOGIN_PASSWORD_EXCEEDED("LOGIN_PASSWORD_EXCEEDED", HttpStatus.UNAUTHORIZED); + LOGIN_PASSWORD_EXCEEDED("LOGIN_PASSWORD_EXCEEDED", HttpStatus.UNAUTHORIZED), + + INACTIVE_ID("INACTIVE_ID", HttpStatus.UNAUTHORIZED); private final String code; private final HttpStatus status; diff --git a/src/main/java/com/kamco/cd/kamcoback/common/utils/CommonStringUtils.java b/src/main/java/com/kamco/cd/kamcoback/common/utils/CommonStringUtils.java index a1db89a3..ee94b72c 100644 --- a/src/main/java/com/kamco/cd/kamcoback/common/utils/CommonStringUtils.java +++ b/src/main/java/com/kamco/cd/kamcoback/common/utils/CommonStringUtils.java @@ -1,13 +1,15 @@ package com.kamco.cd.kamcoback.common.utils; +import com.kamco.cd.kamcoback.auth.BCryptSaltGenerator; import java.util.regex.Pattern; +import org.mindrot.jbcrypt.BCrypt; public class CommonStringUtils { /** * 영문, 숫자, 특수문자를 모두 포함하여 8~20자 이내의 비밀번호 * - * @param password + * @param password 벨리데이션 필요한 패스워드 * @return */ public static boolean isValidPassword(String password) { @@ -15,4 +17,16 @@ public class CommonStringUtils { "^(?=.*[A-Za-z])(?=.*\\d)(?=.*[!@#$%^&*()_+\\-\\[\\]{};':\"\\\\|,.<>/?]).{8,20}$"; return Pattern.matches(passwordPattern, password); } + + /** + * 패스워드 암호화 + * + * @param password 암호화 필요한 패스워드 + * @param employeeNo salt 생성에 필요한 사원번호 + * @return + */ + public static String hashPassword(String password, String employeeNo) { + String salt = BCryptSaltGenerator.generateSaltWithEmployeeNo(employeeNo.trim()); + return BCrypt.hashpw(password.trim(), salt); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/config/api/ApiResponseDto.java b/src/main/java/com/kamco/cd/kamcoback/config/api/ApiResponseDto.java index 969fde31..f428f84b 100644 --- a/src/main/java/com/kamco/cd/kamcoback/config/api/ApiResponseDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/config/api/ApiResponseDto.java @@ -167,6 +167,7 @@ public class ApiResponseDto { LOGIN_ID_NOT_FOUND("아이디를 잘못 입력하셨습니다."), LOGIN_PASSWORD_MISMATCH("비밀번호를 잘못 입력하셨습니다."), LOGIN_PASSWORD_EXCEEDED("비밀번호 오류 횟수를 초과하여 이용하실 수 없습니다.\n로그인 오류에 대해 관리자에게 문의하시기 바랍니다."), + INACTIVE_ID("미사용 아이디 입니다."), INVALID_EMAIL_TOKEN( "You can only reset your password within 24 hours from when the email was sent.\n" + "To reset your password again, please submit a new request through \"Forgot" diff --git a/src/main/java/com/kamco/cd/kamcoback/members/AuthController.java b/src/main/java/com/kamco/cd/kamcoback/members/AuthController.java index a708238e..f21a02c8 100644 --- a/src/main/java/com/kamco/cd/kamcoback/members/AuthController.java +++ b/src/main/java/com/kamco/cd/kamcoback/members/AuthController.java @@ -4,8 +4,6 @@ import com.kamco.cd.kamcoback.auth.CustomUserDetails; import com.kamco.cd.kamcoback.auth.JwtTokenProvider; import com.kamco.cd.kamcoback.auth.RefreshTokenService; import com.kamco.cd.kamcoback.common.enums.StatusType; -import com.kamco.cd.kamcoback.common.enums.error.AuthErrorCode; -import com.kamco.cd.kamcoback.common.exception.CustomApiException; import com.kamco.cd.kamcoback.config.api.ApiResponseDto; import com.kamco.cd.kamcoback.members.dto.MembersDto; import com.kamco.cd.kamcoback.members.dto.SignInRequest; @@ -112,17 +110,9 @@ public class AuthController { Authentication authentication = null; MembersDto.Member member = new MembersDto.Member(); - // 비활성 상태면 임시패스워드를 비교함 - if (StatusType.PENDING.getId().equals(status)) { - if (!authService.isTempPasswordValid(request)) { - throw new CustomApiException(AuthErrorCode.LOGIN_PASSWORD_MISMATCH); - } - } else { - authentication = - authenticationManager.authenticate( - new UsernamePasswordAuthenticationToken( - request.getUsername(), request.getPassword())); - } + authentication = + authenticationManager.authenticate( + new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword())); // PENDING 비활성 상태(새로운 패스워드 입력 해야함) if (StatusType.PENDING.getId().equals(status)) { diff --git a/src/main/java/com/kamco/cd/kamcoback/members/dto/MembersDto.java b/src/main/java/com/kamco/cd/kamcoback/members/dto/MembersDto.java index ab2a7908..3e630882 100644 --- a/src/main/java/com/kamco/cd/kamcoback/members/dto/MembersDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/members/dto/MembersDto.java @@ -28,9 +28,7 @@ public class MembersDto { private String userRole; private String userRoleName; private String name; - private String userId; private String employeeNo; - private String tempPassword; private String status; private String statusName; @JsonFormatDttm private ZonedDateTime createdDttm; @@ -43,9 +41,7 @@ public class MembersDto { UUID uuid, String userRole, String name, - String userId, String employeeNo, - String tempPassword, String status, ZonedDateTime createdDttm, ZonedDateTime updatedDttm, @@ -56,9 +52,7 @@ public class MembersDto { this.userRole = userRole; this.userRoleName = getUserRoleName(userRole); this.name = name; - this.userId = userId; this.employeeNo = employeeNo; - this.tempPassword = tempPassword; this.status = status; this.statusName = getStatusName(status); this.createdDttm = createdDttm; @@ -120,14 +114,16 @@ public class MembersDto { @Size(min = 2, max = 100) private String name; - @Schema(description = "임시 비밀번호", example = "q!w@e#r4") - private String tempPassword; + @NotBlank + @Schema(description = "패스워드", example = "") + @Size(max = 255) + private String password; - public AddReq(String userRole, String employeeNo, String name, String tempPassword) { + public AddReq(String userRole, String employeeNo, String name, String password) { this.userRole = userRole; this.employeeNo = employeeNo; this.name = name; - this.tempPassword = tempPassword; + this.password = password; } } @@ -139,18 +135,18 @@ public class MembersDto { @Size(min = 2, max = 100) private String name; - @Schema(description = "패스워드", example = "") - @Size(max = 255) - private String tempPassword; - @Schema(description = "상태", example = "ACTIVE") @EnumValid(enumClass = StatusType.class, message = "status는 ACTIVE, INACTIVE, DELETED 만 가능합니다.") private String status; - public UpdateReq(String name, String tempPassword, String status) { + @Schema(description = "패스워드", example = "") + @Size(max = 255) + private String password; + + public UpdateReq(String name, String status, String password) { this.name = name; - this.tempPassword = tempPassword; this.status = status; + this.password = password; } } @@ -158,14 +154,15 @@ public class MembersDto { @Setter public static class InitReq { - @Schema(description = "변경 패스워드", example = "") + @Schema(description = "기존 패스워드", example = "") @Size(max = 255) @NotBlank - private String password; + private String oldPassword; - @Schema(description = "초기 패스워드", example = "") + @Schema(description = "신규 패스워드", example = "") + @Size(max = 255) @NotBlank - private String tempPassword; + private String newPassword; } @Getter diff --git a/src/main/java/com/kamco/cd/kamcoback/members/service/AdminService.java b/src/main/java/com/kamco/cd/kamcoback/members/service/AdminService.java index 72d73b5e..8976eb8a 100644 --- a/src/main/java/com/kamco/cd/kamcoback/members/service/AdminService.java +++ b/src/main/java/com/kamco/cd/kamcoback/members/service/AdminService.java @@ -1,6 +1,5 @@ package com.kamco.cd.kamcoback.members.service; -import com.kamco.cd.kamcoback.common.enums.StatusType; import com.kamco.cd.kamcoback.common.exception.CustomApiException; import com.kamco.cd.kamcoback.common.utils.CommonStringUtils; import com.kamco.cd.kamcoback.members.dto.MembersDto; @@ -26,7 +25,7 @@ public class AdminService { */ @Transactional public Long saveMember(MembersDto.AddReq addReq) { - if (!CommonStringUtils.isValidPassword(addReq.getTempPassword())) { + if (!CommonStringUtils.isValidPassword(addReq.getPassword())) { throw new CustomApiException("WRONG_PASSWORD", HttpStatus.BAD_REQUEST); } @@ -41,12 +40,6 @@ public class AdminService { */ @Transactional public void updateMembers(UUID uuid, MembersDto.UpdateReq updateReq) { - if (StatusType.INACTIVE.getId().equals(updateReq.getStatus())) { - // 미사용 처리 - membersCoreService.deleteMember(uuid); - } else { - // 수정 - membersCoreService.updateMembers(uuid, updateReq); - } + membersCoreService.updateMembers(uuid, updateReq); } } diff --git a/src/main/java/com/kamco/cd/kamcoback/members/service/MembersService.java b/src/main/java/com/kamco/cd/kamcoback/members/service/MembersService.java index 538ad387..036d35af 100644 --- a/src/main/java/com/kamco/cd/kamcoback/members/service/MembersService.java +++ b/src/main/java/com/kamco/cd/kamcoback/members/service/MembersService.java @@ -37,7 +37,7 @@ public class MembersService { @Transactional public void resetPassword(String id, MembersDto.InitReq initReq) { - if (!CommonStringUtils.isValidPassword(initReq.getPassword())) { + if (!CommonStringUtils.isValidPassword(initReq.getNewPassword())) { throw new CustomApiException("WRONG_PASSWORD", HttpStatus.BAD_REQUEST); } membersCoreService.resetPassword(id, initReq); diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/core/MembersCoreService.java b/src/main/java/com/kamco/cd/kamcoback/postgres/core/MembersCoreService.java index e3904478..d2ec60f2 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/core/MembersCoreService.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/core/MembersCoreService.java @@ -45,16 +45,16 @@ public class MembersCoreService { // salt 생성, 사번이 salt String salt = BCryptSaltGenerator.generateSaltWithEmployeeNo(addReq.getEmployeeNo().trim()); // 패스워드 암호화, 초기 패스워드 고정 - String hashedPassword = BCrypt.hashpw(addReq.getTempPassword(), salt); + String hashedPassword = BCrypt.hashpw(addReq.getPassword(), salt); MemberEntity memberEntity = new MemberEntity(); memberEntity.setUserId(addReq.getEmployeeNo()); memberEntity.setUserRole(addReq.getUserRole()); - memberEntity.setTempPassword(addReq.getTempPassword().trim()); // 임시 패스워드는 암호화 하지 않음 memberEntity.setPassword(hashedPassword); memberEntity.setName(addReq.getName()); memberEntity.setEmployeeNo(addReq.getEmployeeNo()); memberEntity.setRgstrUidl(userUtil.getId()); + memberEntity.setStatus(StatusType.PENDING.getId()); return membersRepository.save(memberEntity).getId(); } @@ -73,37 +73,25 @@ public class MembersCoreService { memberEntity.setName(updateReq.getName()); } - // 임시 패스워드는 암호화 하지 않음 - if (StringUtils.isNotBlank(updateReq.getTempPassword())) { - /** - * 임시 패스워드가 기존과 다르면 패스워드 변경으로 처리함 상태 PENDING 으로 변경하여 사용자가 로그인할때 패스워드 변경하게함 패스워드 리셋이므로 로그인 - * 실패카운트 초기화처리함 - */ - if (!memberEntity.getTempPassword().equals(updateReq.getTempPassword().trim())) { - // 패스워드 유효성 검사 - if (!CommonStringUtils.isValidPassword(updateReq.getTempPassword())) { - throw new CustomApiException("WRONG_PASSWORD", HttpStatus.BAD_REQUEST); - } + if (StringUtils.isNotBlank(updateReq.getStatus())) { + memberEntity.setStatus(updateReq.getStatus()); + } - memberEntity.setStatus(StatusType.PENDING.getId()); - memberEntity.setLoginFailCount(0); + if (StringUtils.isNotBlank(updateReq.getPassword())) { + + // 패스워드 유효성 검사 + if (!CommonStringUtils.isValidPassword(updateReq.getPassword())) { + throw new CustomApiException("WRONG_PASSWORD", HttpStatus.BAD_REQUEST); } - memberEntity.setTempPassword(updateReq.getTempPassword().trim()); + + String password = + CommonStringUtils.hashPassword(updateReq.getPassword(), memberEntity.getPassword()); + + memberEntity.setStatus(StatusType.PENDING.getId()); + memberEntity.setLoginFailCount(0); + memberEntity.setPassword(password); } memberEntity.setUpdtrUid(userUtil.getId()); - - membersRepository.save(memberEntity); - } - - /** - * 미사용 처리 - * - * @param uuid - */ - public void deleteMember(UUID uuid) { - MemberEntity memberEntity = - membersRepository.findByUUID(uuid).orElseThrow(MemberNotFoundException::new); - memberEntity.setStatus(StatusType.INACTIVE.getId()); membersRepository.save(memberEntity); } @@ -116,18 +104,16 @@ public class MembersCoreService { MemberEntity memberEntity = membersRepository.findByEmployeeNo(id).orElseThrow(() -> new MemberNotFoundException()); - // 임시 패스워드 확인 - if (!memberEntity.getTempPassword().equals(initReq.getTempPassword())) { + // 기존 패스워드 확인 + if (!BCrypt.checkpw(initReq.getOldPassword(), memberEntity.getPassword())) { throw new CustomApiException(AuthErrorCode.LOGIN_PASSWORD_MISMATCH); } - String salt = - BCryptSaltGenerator.generateSaltWithEmployeeNo(memberEntity.getEmployeeNo().trim()); - // 패스워드 암호화 - String hashedPassword = BCrypt.hashpw(initReq.getPassword(), salt); + String password = + CommonStringUtils.hashPassword(initReq.getOldPassword(), memberEntity.getPassword()); - memberEntity.setPassword(hashedPassword); - memberEntity.setStatus("ACTIVE"); + memberEntity.setPassword(password); + memberEntity.setStatus(StatusType.ACTIVE.getId()); memberEntity.setUpdatedDttm(ZonedDateTime.now()); memberEntity.setUpdtrUid(memberEntity.getId()); membersRepository.save(memberEntity); diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MemberEntity.java b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MemberEntity.java index 79e1c1da..19de1956 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MemberEntity.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MemberEntity.java @@ -9,11 +9,13 @@ import jakarta.persistence.Id; import jakarta.persistence.Table; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; +import java.sql.Types; import java.time.ZonedDateTime; import java.util.UUID; import lombok.Getter; import lombok.Setter; import org.hibernate.annotations.ColumnDefault; +import org.hibernate.annotations.JdbcTypeCode; @Getter @Setter @@ -62,7 +64,6 @@ public class MemberEntity { private String password; @Size(max = 20) - @ColumnDefault("'INACTIVE'") @Column(name = "status", length = 20) private String status = StatusType.PENDING.getId(); @@ -90,4 +91,11 @@ public class MemberEntity { @Column(name = "updtr_uid") private Long updtrUid; + + @Column(name = "status_chg_dttm") + private ZonedDateTime statusChgDttm; + + @JdbcTypeCode(Types.CHAR) + @Column(name = "pwd_reset_yn", columnDefinition = "CHAR(1)") + private String pwdResetYn; }