From ed0159eddac7d42599badb3ef77430861a03d901 Mon Sep 17 00:00:00 2001 From: teddy Date: Thu, 11 Dec 2025 12:27:20 +0900 Subject: [PATCH] =?UTF-8?q?=EA=B4=80=EB=A6=AC=EC=9E=90=20=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=EC=88=98=EC=A0=95,=20=EC=97=90=EB=9F=AC=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EA=B3=B5=ED=86=B5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/AuthFailureEventListener.java | 31 ----------- .../auth/CustomAuthenticationProvider.java | 30 +++++++++-- .../cd/kamcoback/common/enums/RoleType.java | 11 +++- .../cd/kamcoback/common/enums/StatusType.java | 25 +++++++++ .../common/enums/error/AuthErrorCode.java | 30 +++++++++++ .../common/exception/CustomApiException.java | 6 +++ .../cd/kamcoback/common/utils/ErrorCode.java | 10 ++++ .../cd/kamcoback/config/SecurityConfig.java | 32 ++++++------ .../kamcoback/config/api/ApiResponseDto.java | 21 +++++--- .../cd/kamcoback/config/enums/EnumType.java | 13 +++++ .../cd/kamcoback/members/AuthController.java | 52 +++++++++++++++---- .../members/MembersApiController.java | 2 +- .../cd/kamcoback/members/dto/MembersDto.java | 20 +++++++ .../members/service/AuthService.java | 21 -------- .../members/service/MembersService.java | 7 +-- .../postgres/core/MembersCoreService.java | 44 ++-------------- 16 files changed, 222 insertions(+), 133 deletions(-) delete mode 100644 src/main/java/com/kamco/cd/kamcoback/auth/AuthFailureEventListener.java create mode 100644 src/main/java/com/kamco/cd/kamcoback/common/enums/StatusType.java create mode 100644 src/main/java/com/kamco/cd/kamcoback/common/enums/error/AuthErrorCode.java create mode 100644 src/main/java/com/kamco/cd/kamcoback/common/utils/ErrorCode.java diff --git a/src/main/java/com/kamco/cd/kamcoback/auth/AuthFailureEventListener.java b/src/main/java/com/kamco/cd/kamcoback/auth/AuthFailureEventListener.java deleted file mode 100644 index 75486d9e..00000000 --- a/src/main/java/com/kamco/cd/kamcoback/auth/AuthFailureEventListener.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.kamco.cd.kamcoback.auth; - -import com.kamco.cd.kamcoback.members.service.AuthService; -import java.util.UUID; -import lombok.RequiredArgsConstructor; -import org.springframework.context.ApplicationListener; -import org.springframework.security.authentication.event.AbstractAuthenticationFailureEvent; -import org.springframework.stereotype.Component; - -@Component -@RequiredArgsConstructor -public class AuthFailureEventListener implements ApplicationListener { - - private final AuthService authService; - - @Override - public void onApplicationEvent(AbstractAuthenticationFailureEvent event) { - // 로그인 시도에 사용된 (username) - Object principal = event.getAuthentication().getPrincipal(); - - if (principal instanceof String username) { - // 로그인 실패 카운트 증가 로직 호출 - authService.loginFail(UUID.fromString(username)); - } - } - - @Override - public boolean supportsAsyncExecution() { - return ApplicationListener.super.supportsAsyncExecution(); - } -} 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 8e6cb1bf..deeaf594 100644 --- a/src/main/java/com/kamco/cd/kamcoback/auth/CustomAuthenticationProvider.java +++ b/src/main/java/com/kamco/cd/kamcoback/auth/CustomAuthenticationProvider.java @@ -1,11 +1,13 @@ package com.kamco.cd.kamcoback.auth; +import com.kamco.cd.kamcoback.common.enums.error.AuthErrorCode; +import com.kamco.cd.kamcoback.common.exception.CustomApiException; import com.kamco.cd.kamcoback.postgres.entity.MemberEntity; import com.kamco.cd.kamcoback.postgres.repository.members.MembersRepository; +import java.time.ZonedDateTime; import lombok.RequiredArgsConstructor; import org.mindrot.jbcrypt.BCrypt; import org.springframework.security.authentication.AuthenticationProvider; -import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; @@ -28,14 +30,34 @@ public class CustomAuthenticationProvider implements AuthenticationProvider { MemberEntity member = membersRepository .findByUserId(username) - .orElseThrow(() -> new BadCredentialsException("ID 또는 비밀번호가 일치하지 않습니다.")); + .orElseThrow(() -> new CustomApiException(AuthErrorCode.LOGIN_ID_NOT_FOUND)); // 2. jBCrypt + 커스텀 salt 로 저장된 패스워드 비교 if (!BCrypt.checkpw(rawPassword, member.getPassword())) { - throw new BadCredentialsException("ID 또는 비밀번호가 일치하지 않습니다."); + // 실패 카운트 저장 + int cnt = member.getLoginFailCount() + 1; + if (cnt >= 5) { + member.setStatus("INACTIVE"); + } + member.setLoginFailCount(cnt); + membersRepository.save(member); + throw new CustomApiException(AuthErrorCode.LOGIN_PASSWORD_MISMATCH); } - // 3. 인증 성공 → UserDetails 생성 + // 3. 패스워드 실패 횟수 체크 + if (member.getLoginFailCount() >= 5) { + throw new CustomApiException(AuthErrorCode.LOGIN_PASSWORD_EXCEEDED); + } + + // 4. 인증 성공 로그인 시간 저장 + if (member.getFirstLoginDttm() == null) { + member.setFirstLoginDttm(ZonedDateTime.now()); + } + member.setLastLoginDttm(ZonedDateTime.now()); + member.setLoginFailCount(0); + membersRepository.save(member); + + // 5. 인증 성공 → UserDetails 생성 CustomUserDetails userDetails = new CustomUserDetails(member); return new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); diff --git a/src/main/java/com/kamco/cd/kamcoback/common/enums/RoleType.java b/src/main/java/com/kamco/cd/kamcoback/common/enums/RoleType.java index 3da213ea..d1945c7e 100644 --- a/src/main/java/com/kamco/cd/kamcoback/common/enums/RoleType.java +++ b/src/main/java/com/kamco/cd/kamcoback/common/enums/RoleType.java @@ -7,7 +7,7 @@ import lombok.Getter; @Getter @AllArgsConstructor public enum RoleType implements EnumType { - ROLE_ADMIN("시스템 관리자"), + ROLE_ADMIN("관리자"), ROLE_LABELER("라벨러"), ROLE_REVIEWER("검수자"); @@ -22,4 +22,13 @@ public enum RoleType implements EnumType { public String getText() { return desc; } + + public static RoleType from(String value) { + for (RoleType type : values()) { + if (type.name().equalsIgnoreCase(value)) { + return type; + } + } + return null; + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/common/enums/StatusType.java b/src/main/java/com/kamco/cd/kamcoback/common/enums/StatusType.java new file mode 100644 index 00000000..641d3de5 --- /dev/null +++ b/src/main/java/com/kamco/cd/kamcoback/common/enums/StatusType.java @@ -0,0 +1,25 @@ +package com.kamco.cd.kamcoback.common.enums; + +import com.kamco.cd.kamcoback.config.enums.EnumType; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum StatusType implements EnumType { + ACTIVE("활성"), + INACTIVE("비활성"), + ARCHIVED("탈퇴"); + + private final String desc; + + @Override + public String getId() { + return name(); + } + + @Override + public String getText() { + return desc; + } +} 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 new file mode 100644 index 00000000..3eca6ef1 --- /dev/null +++ b/src/main/java/com/kamco/cd/kamcoback/common/enums/error/AuthErrorCode.java @@ -0,0 +1,30 @@ +package com.kamco.cd.kamcoback.common.enums.error; + +import com.kamco.cd.kamcoback.common.utils.ErrorCode; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +public enum AuthErrorCode implements ErrorCode { + + // 🔐 로그인 관련 + LOGIN_ID_NOT_FOUND( + "LOGIN_ID_NOT_FOUND", + HttpStatus.UNAUTHORIZED), + + LOGIN_PASSWORD_MISMATCH( + "LOGIN_PASSWORD_MISMATCH", + HttpStatus.UNAUTHORIZED), + + LOGIN_PASSWORD_EXCEEDED( + "LOGIN_PASSWORD_EXCEEDED", + HttpStatus.UNAUTHORIZED); + + private final String code; + private final HttpStatus status; + + AuthErrorCode(String code, HttpStatus status) { + this.code = code; + this.status = status; + } +} diff --git a/src/main/java/com/kamco/cd/kamcoback/common/exception/CustomApiException.java b/src/main/java/com/kamco/cd/kamcoback/common/exception/CustomApiException.java index 482d5f6c..cd3a3a1a 100644 --- a/src/main/java/com/kamco/cd/kamcoback/common/exception/CustomApiException.java +++ b/src/main/java/com/kamco/cd/kamcoback/common/exception/CustomApiException.java @@ -1,5 +1,6 @@ package com.kamco.cd.kamcoback.common.exception; +import com.kamco.cd.kamcoback.common.utils.ErrorCode; import lombok.Getter; import org.springframework.http.HttpStatus; @@ -19,4 +20,9 @@ public class CustomApiException extends RuntimeException { this.codeName = codeName; this.status = status; } + + public CustomApiException(ErrorCode errorCode) { + this.codeName = errorCode.getCode(); + this.status = errorCode.getStatus(); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/common/utils/ErrorCode.java b/src/main/java/com/kamco/cd/kamcoback/common/utils/ErrorCode.java new file mode 100644 index 00000000..8ace8fe1 --- /dev/null +++ b/src/main/java/com/kamco/cd/kamcoback/common/utils/ErrorCode.java @@ -0,0 +1,10 @@ +package com.kamco.cd.kamcoback.common.utils; + +import org.springframework.http.HttpStatus; + +public interface ErrorCode { + + String getCode(); + + HttpStatus getStatus(); +} diff --git a/src/main/java/com/kamco/cd/kamcoback/config/SecurityConfig.java b/src/main/java/com/kamco/cd/kamcoback/config/SecurityConfig.java index a952e535..448fa31f 100644 --- a/src/main/java/com/kamco/cd/kamcoback/config/SecurityConfig.java +++ b/src/main/java/com/kamco/cd/kamcoback/config/SecurityConfig.java @@ -6,12 +6,14 @@ import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.CorsConfigurationSource; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; @@ -40,21 +42,21 @@ public class SecurityConfig { customAuthenticationProvider) // 로그인 패스워드 비교방식 스프링 기본 Provider 사용안함 커스텀 사용 .authorizeHttpRequests( auth -> - auth.anyRequest().permitAll()); -// requestMatchers(HttpMethod.OPTIONS, "/**") -// .permitAll() // preflight 허용 -// .requestMatchers( -// "/api/auth/signin", -// "/api/auth/refresh", -// "/swagger-ui/**", -// "/v3/api-docs/**") -// .permitAll() -// .anyRequest() -// .authenticated()) -// .addFilterBefore( -// jwtAuthenticationFilter, -// UsernamePasswordAuthenticationFilter -// .class) // 요청 들어오면 먼저 JWT 토큰 검사 후 security context 에 사용자 정보 저장. + auth.requestMatchers(HttpMethod.OPTIONS, "/**") + .permitAll() // preflight 허용 + .requestMatchers( + "/api/auth/signin", + "/api/auth/refresh", + "/swagger-ui/**", + "/api/members/{memberId}/password", + "/v3/api-docs/**") + .permitAll() + .anyRequest() + .authenticated()) + .addFilterBefore( + jwtAuthenticationFilter, + UsernamePasswordAuthenticationFilter + .class) // 요청 들어오면 먼저 JWT 토큰 검사 후 security context 에 사용자 정보 저장. ; return http.build(); 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 3cd2d792..de466c5d 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 @@ -20,9 +20,11 @@ public class ApiResponseDto { @JsonInclude(JsonInclude.Include.NON_NULL) private T errorData; - @JsonIgnore private HttpStatus httpStatus; + @JsonIgnore + private HttpStatus httpStatus; - @JsonIgnore private Long errorLogUid; + @JsonIgnore + private Long errorLogUid; public ApiResponseDto(T data) { this.data = data; @@ -47,7 +49,7 @@ public class ApiResponseDto { } public ApiResponseDto( - ApiResponseCode code, String message, HttpStatus httpStatus, Long errorLogUid) { + ApiResponseCode code, String message, HttpStatus httpStatus, Long errorLogUid) { this.error = new Error(code.getId(), message); this.httpStatus = httpStatus; this.errorLogUid = errorLogUid; @@ -88,17 +90,17 @@ public class ApiResponseDto { } public static ApiResponseDto createException( - ApiResponseCode code, String message, HttpStatus httpStatus) { + ApiResponseCode code, String message, HttpStatus httpStatus) { return new ApiResponseDto<>(code, message, httpStatus); } public static ApiResponseDto createException( - ApiResponseCode code, String message, HttpStatus httpStatus, Long errorLogUid) { + ApiResponseCode code, String message, HttpStatus httpStatus, Long errorLogUid) { return new ApiResponseDto<>(code, message, httpStatus, errorLogUid); } public static ApiResponseDto createException( - ApiResponseCode code, String message, T data) { + ApiResponseCode code, String message, T data) { return new ApiResponseDto<>(code, message, data); } @@ -114,7 +116,9 @@ public class ApiResponseDto { } } - /** Error가 아닌 Business상 성공이거나 실패인 경우, 메세지 함께 전달하기 위한 object */ + /** + * Error가 아닌 Business상 성공이거나 실패인 경우, 메세지 함께 전달하기 위한 object + */ @Getter public static class ResponseObj { @@ -164,6 +168,9 @@ public class ApiResponseDto { NOT_FOUND_USER_FOR_EMAIL("이메일로 유저를 찾을 수 없습니다."), NOT_FOUND_USER("사용자를 찾을 수 없습니다."), UNPROCESSABLE_ENTITY("이 데이터는 삭제할 수 없습니다."), + LOGIN_ID_NOT_FOUND("아이디를 잘못 입력하셨습니다."), + LOGIN_PASSWORD_MISMATCH("비밀번호를 잘못 입력하셨습니다."), + LOGIN_PASSWORD_EXCEEDED("비밀번호 오류 횟수를 초과하여 이용하실 수 없습니다.\n로그인 오류에 대해 관리자에게 문의하시기 바랍니다."), 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/config/enums/EnumType.java b/src/main/java/com/kamco/cd/kamcoback/config/enums/EnumType.java index 274bfe72..1be49253 100644 --- a/src/main/java/com/kamco/cd/kamcoback/config/enums/EnumType.java +++ b/src/main/java/com/kamco/cd/kamcoback/config/enums/EnumType.java @@ -5,4 +5,17 @@ public interface EnumType { String getId(); String getText(); + + // code로 text + static & EnumType> E fromId(Class enumClass, String id) { + if (id == null) { + return null; + } + for (E e : enumClass.getEnumConstants()) { + if (id.equalsIgnoreCase(e.getId())) { + return e; + } + } + return null; // 못 찾으면 null + } } 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 47b76169..e948c14e 100644 --- a/src/main/java/com/kamco/cd/kamcoback/members/AuthController.java +++ b/src/main/java/com/kamco/cd/kamcoback/members/AuthController.java @@ -7,6 +7,7 @@ import com.kamco.cd.kamcoback.members.dto.SignInRequest; import com.kamco.cd.kamcoback.members.service.AuthService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; @@ -14,7 +15,6 @@ import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpServletResponse; import java.nio.file.AccessDeniedException; import java.time.Duration; -import java.util.UUID; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpHeaders; @@ -55,12 +55,43 @@ public class AuthController { content = @Content(schema = @Schema(implementation = TokenResponse.class))), @ApiResponse( responseCode = "401", - description = "ID 또는 비밀번호 불일치", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))), - @ApiResponse( - responseCode = "400", - description = "미사용 상태", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))) + description = "로그인 실패 (아이디/비밀번호 오류, 계정잠금 등)", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = { + @ExampleObject( + name = "아이디 입력 오류", + description = "존재하지 않는 아이디", + value = """ + { + "code": "LOGIN_ID_NOT_FOUND", + "message": "아이디를 잘못 입력하셨습니다.", + "detail": null + } + """), + @ExampleObject( + name = "비밀번호 입력 오류 (4회 이하)", + description = "아이디는 정상, 비밀번호를 여러 번 틀린 경우", + value = """ + { + "code": "LOGIN_PASSWORD_MISMATCH", + "message": "비밀번호를 잘못 입력하셨습니다.", + "detail": "비밀번호 입력 오류 3회, 2회 남았습니다." + } + """), + @ExampleObject( + name = "비밀번호 오류 횟수 초과", + description = "비밀번호 5회 이상 오류로 계정 잠김", + value = """ + { + "code": "LOGIN_PASSWORD_EXCEEDED", + "message": "비밀번호 오류 횟수를 초과하여 이용하실 수 없습니다.", + "detail": "로그인 오류에 대해 관리자에게 문의하시기 바랍니다." + } + """) + } + )) }) public ApiResponseDto signin( @io.swagger.v3.oas.annotations.parameters.RequestBody( @@ -75,15 +106,14 @@ public class AuthController { new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword())); String status = authService.getUserStatus(request); - if ("INACTIVE".equals(status)) { + + // INACTIVE 비활성 상태(새로운 패스워드 입력 해야함), ARCHIVED 탈퇴 + if (!"ACTIVE".equals(status)) { return ApiResponseDto.ok(new TokenResponse(status, null, null)); } String username = authentication.getName(); // UserDetailsService 에서 사용한 username - // 로그인 시간 저장 - authService.saveLogin(UUID.fromString(username)); - String accessToken = jwtTokenProvider.createAccessToken(username); String refreshToken = jwtTokenProvider.createRefreshToken(username); diff --git a/src/main/java/com/kamco/cd/kamcoback/members/MembersApiController.java b/src/main/java/com/kamco/cd/kamcoback/members/MembersApiController.java index 6f63553c..633bf10e 100644 --- a/src/main/java/com/kamco/cd/kamcoback/members/MembersApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/members/MembersApiController.java @@ -64,7 +64,7 @@ public class MembersApiController { @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) }) @PatchMapping("/{memberId}/password") - public ApiResponseDto resetPassword(@PathVariable Long memberId, @RequestBody @Valid MembersDto.InitReq initReq) { + public ApiResponseDto resetPassword(@PathVariable String memberId, @RequestBody @Valid MembersDto.InitReq initReq) { membersService.resetPassword(memberId, initReq); return ApiResponseDto.createOK(memberId); } 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 d28d39ca..3f5f0616 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 @@ -1,6 +1,9 @@ package com.kamco.cd.kamcoback.members.dto; +import com.kamco.cd.kamcoback.common.enums.RoleType; +import com.kamco.cd.kamcoback.common.enums.StatusType; import com.kamco.cd.kamcoback.common.utils.interfaces.JsonFormatDttm; +import com.kamco.cd.kamcoback.config.enums.EnumType; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Size; @@ -22,11 +25,13 @@ public class MembersDto { private Long id; private UUID uuid; 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; @JsonFormatDttm @@ -40,11 +45,13 @@ public class MembersDto { Long id, UUID uuid, String userRole, + String userRoleName, String name, String userId, String employeeNo, String tempPassword, String status, + String statusName, ZonedDateTime createdDttm, ZonedDateTime updatedDttm, ZonedDateTime firstLoginDttm, @@ -53,16 +60,29 @@ public class MembersDto { this.id = id; this.uuid = uuid; 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; this.updatedDttm = updatedDttm; this.firstLoginDttm = firstLoginDttm; this.lastLoginDttm = lastLoginDttm; } + + private String getUserRoleName(String roleId) { + RoleType type = EnumType.fromId(RoleType.class, roleId); + return type.getText(); + } + + private String getStatusName(String status) { + StatusType type = EnumType.fromId(StatusType.class, status); + return type.getText(); + } + } @Getter diff --git a/src/main/java/com/kamco/cd/kamcoback/members/service/AuthService.java b/src/main/java/com/kamco/cd/kamcoback/members/service/AuthService.java index 5433750b..1dcfc578 100644 --- a/src/main/java/com/kamco/cd/kamcoback/members/service/AuthService.java +++ b/src/main/java/com/kamco/cd/kamcoback/members/service/AuthService.java @@ -2,7 +2,6 @@ package com.kamco.cd.kamcoback.members.service; import com.kamco.cd.kamcoback.members.dto.SignInRequest; import com.kamco.cd.kamcoback.postgres.core.MembersCoreService; -import java.util.UUID; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -14,26 +13,6 @@ public class AuthService { private final MembersCoreService membersCoreService; - /** - * 로그인 일시 저장 - * - * @param uuid - */ - @Transactional - public void saveLogin(UUID uuid) { - membersCoreService.saveLogin(uuid); - } - - /** - * 로그인 실패 저장 - * - * @param uuid - */ - @Transactional - public void loginFail(UUID uuid) { - membersCoreService.loginFail(uuid); - } - /** * 사용자 상태 조회 * 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 945d4868..d68352a4 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 @@ -35,7 +35,7 @@ public class MembersService { * @param initReq */ @Transactional - public void resetPassword(Long id, MembersDto.InitReq initReq) { + public void resetPassword(String id, MembersDto.InitReq initReq) { if (!isValidPassword(initReq.getPassword())) { throw new CustomApiException("WRONG_PASSWORD", HttpStatus.BAD_REQUEST); } @@ -49,7 +49,8 @@ public class MembersService { * @return */ private boolean isValidPassword(String password) { - String regex = "^(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)(?=.*[!@#$]).{8,20}$"; - return Pattern.matches(regex, password); + String passwordPattern = + "^(?=.*[A-Za-z])(?=.*\\d)(?=.*[!@#$%^&*()_+\\-\\[\\]{};':\"\\\\|,.<>/?]).{8,20}$"; + return Pattern.matches(passwordPattern, password); } } 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 d1a1b642..756e9f71 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 @@ -1,6 +1,8 @@ package com.kamco.cd.kamcoback.postgres.core; import com.kamco.cd.kamcoback.auth.BCryptSaltGenerator; +import com.kamco.cd.kamcoback.common.enums.error.AuthErrorCode; +import com.kamco.cd.kamcoback.common.exception.CustomApiException; import com.kamco.cd.kamcoback.members.dto.MembersDto; import com.kamco.cd.kamcoback.members.dto.MembersDto.AddReq; import com.kamco.cd.kamcoback.members.dto.MembersDto.Basic; @@ -8,7 +10,6 @@ import com.kamco.cd.kamcoback.members.dto.SignInRequest; import com.kamco.cd.kamcoback.members.exception.MemberException.DuplicateMemberException; import com.kamco.cd.kamcoback.members.exception.MemberException.DuplicateMemberException.Field; import com.kamco.cd.kamcoback.members.exception.MemberException.MemberNotFoundException; -import com.kamco.cd.kamcoback.members.exception.MemberException.PasswordNotFoundException; import com.kamco.cd.kamcoback.postgres.entity.MemberEntity; import com.kamco.cd.kamcoback.postgres.repository.members.MembersRepository; import java.time.ZonedDateTime; @@ -99,12 +100,12 @@ public class MembersCoreService { * * @param id */ - public void resetPassword(Long id, MembersDto.InitReq initReq) { + public void resetPassword(String id, MembersDto.InitReq initReq) { MemberEntity memberEntity = - membersRepository.findById(id).orElseThrow(() -> new MemberNotFoundException()); + membersRepository.findByUserId(id).orElseThrow(() -> new MemberNotFoundException()); if (!memberEntity.getTempPassword().equals(initReq.getTempPassword())) { - throw new PasswordNotFoundException(); + throw new CustomApiException(AuthErrorCode.LOGIN_PASSWORD_MISMATCH); } String salt = @@ -129,41 +130,6 @@ public class MembersCoreService { return membersRepository.findByMembers(searchReq); } - /** - * 최초 로그인 저장 마지막 로그인 저장 - * - * @param uuid - */ - public void saveLogin(UUID uuid) { - MemberEntity memberEntity = - membersRepository.findByUUID(uuid).orElseThrow(() -> new MemberNotFoundException()); - - if (memberEntity.getFirstLoginDttm() == null) { - memberEntity.setFirstLoginDttm(ZonedDateTime.now()); - } - memberEntity.setLastLoginDttm(ZonedDateTime.now()); - memberEntity.setLoginFailCount(0); - membersRepository.save(memberEntity); - } - - /** - * 로그인 실패시 상태 저장 - * - * @param uuid - */ - public void loginFail(UUID uuid) { - MemberEntity memberEntity = - membersRepository.findByUUID(uuid).orElseThrow(() -> new MemberNotFoundException()); - - int failCnt = memberEntity.getLoginFailCount() + 1; - if (failCnt >= 5) { - memberEntity.setStatus("INACTIVE"); - } - - memberEntity.setLoginFailCount(failCnt); - membersRepository.save(memberEntity); - } - /** * 사용자 상태 조회 *