Merge remote-tracking branch 'origin/feat/dev_251201' into feat/dev_251201
This commit is contained in:
@@ -70,6 +70,10 @@ public class ApiResponseAdvice implements ResponseBodyAdvice<Object> {
|
|||||||
// audit 에는 long 타입 user_id가 들어가지만 토큰 sub은 uuid여서 user_id 가져오기
|
// audit 에는 long 타입 user_id가 들어가지만 토큰 sub은 uuid여서 user_id 가져오기
|
||||||
userid = customUserDetails.getMember().getId();
|
userid = customUserDetails.getMember().getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String requestBody = ApiLogFunction.getRequestBody(servletRequest, contentWrapper);
|
||||||
|
requestBody = maskSensitiveFields(requestBody); // 로그 저장전에 중요정보 마스킹
|
||||||
|
|
||||||
// TODO: menuUid 를 동적으로 가져오게끔 해야함
|
// TODO: menuUid 를 동적으로 가져오게끔 해야함
|
||||||
AuditLogEntity log =
|
AuditLogEntity log =
|
||||||
new AuditLogEntity(
|
new AuditLogEntity(
|
||||||
@@ -79,13 +83,33 @@ public class ApiResponseAdvice implements ResponseBodyAdvice<Object> {
|
|||||||
"MU_01_01",
|
"MU_01_01",
|
||||||
ip,
|
ip,
|
||||||
servletRequest.getRequestURI(),
|
servletRequest.getRequestURI(),
|
||||||
ApiLogFunction.getRequestBody(servletRequest, contentWrapper),
|
requestBody,
|
||||||
apiResponse.getErrorLogUid());
|
apiResponse.getErrorLogUid());
|
||||||
|
|
||||||
// tb_audit_log 테이블 저장
|
// tb_audit_log 테이블 저장
|
||||||
auditLogRepository.save(log);
|
auditLogRepository.save(log);
|
||||||
}
|
}
|
||||||
|
|
||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 마스킹
|
||||||
|
*
|
||||||
|
* @param json
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private String maskSensitiveFields(String json) {
|
||||||
|
if (json == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// password 마스킹
|
||||||
|
json = json.replaceAll("\"password\"\\s*:\\s*\"[^\"]*\"", "\"password\":\"****\"");
|
||||||
|
|
||||||
|
// 토큰 마스킹
|
||||||
|
json = json.replaceAll("\"accessToken\"\\s*:\\s*\"[^\"]*\"", "\"accessToken\":\"****\"");
|
||||||
|
json = json.replaceAll("\"refreshToken\"\\s*:\\s*\"[^\"]*\"", "\"refreshToken\":\"****\"");
|
||||||
|
|
||||||
|
return json;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package com.kamco.cd.kamcoback.members;
|
|||||||
|
|
||||||
import com.kamco.cd.kamcoback.auth.JwtTokenProvider;
|
import com.kamco.cd.kamcoback.auth.JwtTokenProvider;
|
||||||
import com.kamco.cd.kamcoback.auth.RefreshTokenService;
|
import com.kamco.cd.kamcoback.auth.RefreshTokenService;
|
||||||
|
import com.kamco.cd.kamcoback.config.api.ApiResponseDto;
|
||||||
|
import com.kamco.cd.kamcoback.members.dto.SignInRequest;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.media.Content;
|
import io.swagger.v3.oas.annotations.media.Content;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
@@ -9,6 +11,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
|||||||
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import java.nio.file.AccessDeniedException;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
@@ -52,7 +55,7 @@ public class AuthController {
|
|||||||
description = "ID 또는 비밀번호 불일치",
|
description = "ID 또는 비밀번호 불일치",
|
||||||
content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
|
content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
|
||||||
})
|
})
|
||||||
public ResponseEntity<TokenResponse> signin(
|
public ApiResponseDto<TokenResponse> signin(
|
||||||
@io.swagger.v3.oas.annotations.parameters.RequestBody(
|
@io.swagger.v3.oas.annotations.parameters.RequestBody(
|
||||||
description = "로그인 요청 정보",
|
description = "로그인 요청 정보",
|
||||||
required = true)
|
required = true)
|
||||||
@@ -61,7 +64,7 @@ public class AuthController {
|
|||||||
HttpServletResponse response) {
|
HttpServletResponse response) {
|
||||||
Authentication authentication =
|
Authentication authentication =
|
||||||
authenticationManager.authenticate(
|
authenticationManager.authenticate(
|
||||||
new UsernamePasswordAuthenticationToken(request.username(), request.password()));
|
new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword()));
|
||||||
|
|
||||||
String username = authentication.getName(); // UserDetailsService 에서 사용한 username
|
String username = authentication.getName(); // UserDetailsService 에서 사용한 username
|
||||||
|
|
||||||
@@ -83,8 +86,7 @@ public class AuthController {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString());
|
response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString());
|
||||||
|
return ApiResponseDto.createOK(new TokenResponse(accessToken));
|
||||||
return ResponseEntity.ok(new TokenResponse(accessToken));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/refresh")
|
@PostMapping("/refresh")
|
||||||
@@ -99,16 +101,16 @@ public class AuthController {
|
|||||||
description = "만료되었거나 유효하지 않은 리프레시 토큰",
|
description = "만료되었거나 유효하지 않은 리프레시 토큰",
|
||||||
content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
|
content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
|
||||||
})
|
})
|
||||||
public ResponseEntity<TokenResponse> refresh(String refreshToken, HttpServletResponse response) {
|
public ResponseEntity<TokenResponse> refresh(String refreshToken, HttpServletResponse response) throws AccessDeniedException {
|
||||||
if (refreshToken == null || !jwtTokenProvider.isValidToken(refreshToken)) {
|
if (refreshToken == null || !jwtTokenProvider.isValidToken(refreshToken)) {
|
||||||
return ResponseEntity.status(401).build();
|
throw new AccessDeniedException("만료되었거나 유효하지 않은 리프레시 토큰 입니다.");
|
||||||
}
|
}
|
||||||
|
|
||||||
String username = jwtTokenProvider.getSubject(refreshToken);
|
String username = jwtTokenProvider.getSubject(refreshToken);
|
||||||
|
|
||||||
// Redis에 저장된 RefreshToken과 일치하는지 확인
|
// Redis에 저장된 RefreshToken과 일치하는지 확인
|
||||||
if (!refreshTokenService.validate(username, refreshToken)) {
|
if (!refreshTokenService.validate(username, refreshToken)) {
|
||||||
return ResponseEntity.status(401).build();
|
throw new AccessDeniedException("만료되었거나 유효하지 않은 리프레시 토큰 입니다.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 새 토큰 발급
|
// 새 토큰 발급
|
||||||
@@ -141,7 +143,7 @@ public class AuthController {
|
|||||||
description = "로그아웃 성공",
|
description = "로그아웃 성공",
|
||||||
content = @Content(schema = @Schema(implementation = Void.class)))
|
content = @Content(schema = @Schema(implementation = Void.class)))
|
||||||
})
|
})
|
||||||
public ResponseEntity<Void> logout(Authentication authentication, HttpServletResponse response) {
|
public ApiResponseDto<ResponseEntity<Object>> logout(Authentication authentication, HttpServletResponse response) {
|
||||||
if (authentication != null) {
|
if (authentication != null) {
|
||||||
String username = authentication.getName();
|
String username = authentication.getName();
|
||||||
// Redis에서 RefreshToken 삭제
|
// Redis에서 RefreshToken 삭제
|
||||||
@@ -159,14 +161,7 @@ public class AuthController {
|
|||||||
.build();
|
.build();
|
||||||
response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString());
|
response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString());
|
||||||
|
|
||||||
return ResponseEntity.noContent().build();
|
return ApiResponseDto.createOK(ResponseEntity.noContent().build());
|
||||||
}
|
|
||||||
|
|
||||||
@Schema(description = "로그인 요청 DTO")
|
|
||||||
public record SignInRequest(
|
|
||||||
@Schema(description = "사번", example = "11111") String username,
|
|
||||||
@Schema(description = "비밀번호", example = "kamco1234!") String password) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public record TokenResponse(String accessToken) {
|
public record TokenResponse(String accessToken) {
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.kamco.cd.kamcoback.members.dto;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString(exclude = "password")
|
||||||
|
public class SignInRequest {
|
||||||
|
|
||||||
|
private String username;
|
||||||
|
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
|
||||||
|
private String password;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user