Skip to content

Commit a39f148

Browse files
authored
️♻️ refactor: 시큐리티 구조 개선 (#73)
* refactor: 시큐리티 구조개선, 예외처리 개선 * feat: 임시로 예외 세부내용을 처리하도록 변경
1 parent cbd300f commit a39f148

13 files changed

+164
-84
lines changed

src/main/java/com/sponus/sponusbe/auth/jwt/exception/CustomExpiredJwtException.java

Lines changed: 0 additions & 8 deletions
This file was deleted.

src/main/java/com/sponus/sponusbe/auth/jwt/exception/CustomMalformedException.java

Lines changed: 0 additions & 8 deletions
This file was deleted.

src/main/java/com/sponus/sponusbe/auth/jwt/exception/CustomNoTokenException.java

Lines changed: 0 additions & 8 deletions
This file was deleted.

src/main/java/com/sponus/sponusbe/auth/jwt/exception/CustomSignatureException.java

Lines changed: 0 additions & 8 deletions
This file was deleted.
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.sponus.sponusbe.auth.jwt.exception;
2+
3+
import java.io.IOException;
4+
5+
import org.springframework.http.HttpStatus;
6+
import org.springframework.security.access.AccessDeniedException;
7+
import org.springframework.security.web.access.AccessDeniedHandler;
8+
import org.springframework.stereotype.Component;
9+
10+
import com.sponus.sponusbe.auth.jwt.util.HttpResponseUtil;
11+
12+
import jakarta.servlet.http.HttpServletRequest;
13+
import jakarta.servlet.http.HttpServletResponse;
14+
import lombok.extern.slf4j.Slf4j;
15+
16+
/**
17+
* 인증된 사용자가 필요한 권한없이 접근하려고 할 때 발생하는 예외 처리
18+
*/
19+
@Slf4j
20+
@Component
21+
public class JwtAccessDeniedHandler implements AccessDeniedHandler {
22+
23+
@Override
24+
public void handle(HttpServletRequest request, HttpServletResponse response,
25+
AccessDeniedException accessDeniedException) throws IOException {
26+
log.warn("Access Denied: ", accessDeniedException);
27+
28+
HttpResponseUtil.setErrorResponse(response, HttpStatus.FORBIDDEN,
29+
SecurityErrorCode.FORBIDDEN.getErrorResponse());
30+
}
31+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package com.sponus.sponusbe.auth.jwt.exception;
2+
3+
import java.io.IOException;
4+
5+
import org.springframework.http.HttpStatus;
6+
import org.springframework.security.core.AuthenticationException;
7+
import org.springframework.security.web.AuthenticationEntryPoint;
8+
import org.springframework.stereotype.Component;
9+
10+
import com.sponus.sponusbe.auth.jwt.util.HttpResponseUtil;
11+
import com.sponus.sponusbe.global.common.ApiResponse;
12+
13+
import jakarta.servlet.http.HttpServletRequest;
14+
import jakarta.servlet.http.HttpServletResponse;
15+
import lombok.extern.slf4j.Slf4j;
16+
17+
/**
18+
* 사용자가 인증되지 않은 상태에서 접근하려고 할 때 발생하는 예외 처리
19+
*/
20+
@Slf4j
21+
@Component
22+
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
23+
24+
@Override
25+
public void commence(HttpServletRequest request, HttpServletResponse response,
26+
AuthenticationException authException)
27+
throws IOException {
28+
HttpStatus httpStatus;
29+
ApiResponse<String> errorResponse;
30+
31+
log.error(">>>>>> AuthenticationException: ", authException);
32+
httpStatus = HttpStatus.UNAUTHORIZED;
33+
errorResponse = ApiResponse.onFailure(
34+
SecurityErrorCode.UNAUTHORIZED.getCode(),
35+
SecurityErrorCode.UNAUTHORIZED.getMessage(),
36+
authException.getMessage());
37+
38+
HttpResponseUtil.setErrorResponse(response, httpStatus, errorResponse);
39+
}
40+
}

src/main/java/com/sponus/sponusbe/auth/jwt/exception/SecurityCustomException.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,20 @@
33
import com.sponus.sponusbe.global.common.BaseErrorCode;
44
import com.sponus.sponusbe.global.common.exception.CustomException;
55

6+
import lombok.Getter;
7+
8+
@Getter
69
public class SecurityCustomException extends CustomException {
710

11+
private final Throwable cause;
12+
813
public SecurityCustomException(BaseErrorCode errorCode) {
914
super(errorCode);
15+
this.cause = null;
16+
}
17+
18+
public SecurityCustomException(BaseErrorCode errorCode, Throwable cause) {
19+
super(errorCode);
20+
this.cause = cause;
1021
}
1122
}

src/main/java/com/sponus/sponusbe/auth/jwt/exception/SecurityErrorCode.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,14 @@
1212
@AllArgsConstructor
1313
public enum SecurityErrorCode implements BaseErrorCode {
1414

15-
INVALID_TOKEN(HttpStatus.BAD_REQUEST, "4001", "유효하지 않은 형식의 토큰입니다."),
16-
TOKEN_EXCEPTION(HttpStatus.UNAUTHORIZED, "4011", "토큰 처리 중 예외가 발생했습니다."),
17-
UNAUTHORIZED(HttpStatus.UNAUTHORIZED, "4012", "권한이 없습니다."),
18-
TOKEN_EXPIRED(HttpStatus.UNAUTHORIZED, "4013", "만료된 토큰입니다."),
19-
SIGNATURE_ERROR(HttpStatus.UNAUTHORIZED, "4014", "무결하지 않은 토큰입니다."),
20-
TOKEN_NOT_FOUND(HttpStatus.UNAUTHORIZED, "4015", "토큰이 존재하지 않습니다."),
21-
INTERNAL_SECURITY_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "5001", "서버 에러가 발생했습니다. 관리자에게 문의해주세요.");
15+
INVALID_TOKEN(HttpStatus.BAD_REQUEST, "SEC4001", "잘못된 형식의 토큰입니다."),
16+
UNAUTHORIZED(HttpStatus.UNAUTHORIZED, "SEC4010", "인증이 필요합니다."),
17+
TOKEN_EXPIRED(HttpStatus.UNAUTHORIZED, "SEC4011", "토큰이 만료되었습니다."),
18+
TOKEN_SIGNATURE_ERROR(HttpStatus.UNAUTHORIZED, "SEC4012", "토큰이 위조되었거나 손상되었습니다."),
19+
FORBIDDEN(HttpStatus.FORBIDDEN, "SEC4030", "권한이 없습니다."),
20+
TOKEN_NOT_FOUND(HttpStatus.UNAUTHORIZED, "SEC4041", "토큰이 존재하지 않습니다."),
21+
INTERNAL_SECURITY_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "SEC5000", "인증 처리 중 서버 에러가 발생했습니다."),
22+
INTERNAL_TOKEN_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "SEC5001", "토큰 처리 중 서버 에러가 발생했습니다.");
2223

2324
private final HttpStatus httpStatus;
2425
private final String code;

src/main/java/com/sponus/sponusbe/auth/jwt/filter/JwtFilter.java renamed to src/main/java/com/sponus/sponusbe/auth/jwt/filter/JwtAuthenticationFilter.java

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
import lombok.RequiredArgsConstructor;
2828

2929
@RequiredArgsConstructor
30-
public class JwtFilter extends OncePerRequestFilter {
30+
public class JwtAuthenticationFilter extends OncePerRequestFilter {
3131

3232
private final JwtUtil jwtUtil;
3333
private final RedisUtil redisUtil;
@@ -51,8 +51,7 @@ protected void doFilterInternal(
5151
}
5252

5353
// logout 처리된 accessToken
54-
if (redisUtil.get(accessToken) != null &&
55-
redisUtil.get(accessToken).equals("logout")) {
54+
if (redisUtil.get(accessToken) != null && redisUtil.get(accessToken).equals("logout")) {
5655
logger.info("[*] Logout accessToken");
5756
filterChain.doFilter(cachedHttpServletRequest, response);
5857
return;
@@ -63,7 +62,6 @@ protected void doFilterInternal(
6362
filterChain.doFilter(cachedHttpServletRequest, response);
6463
} catch (ExpiredJwtException e) {
6564
logger.warn("[*] case : accessToken Expired");
66-
6765
// accessToken 만료 시 Body에 있는 refreshToken 확인
6866
String refreshToken = request.getHeader("refreshToken");
6967

@@ -75,12 +73,12 @@ protected void doFilterInternal(
7573
JwtPair reissueTokens = jwtUtil.reissueToken(refreshToken);
7674
setSuccessResponse(response, CREATED, reissueTokens);
7775
}
78-
} catch (ExpiredJwtException e1) {
76+
} catch (ExpiredJwtException eje) {
7977
logger.info("[*] case : accessToken, refreshToken expired");
80-
throw new SecurityCustomException(SecurityErrorCode.TOKEN_EXPIRED);
81-
} catch (IllegalArgumentException e2) {
78+
throw new SecurityCustomException(SecurityErrorCode.TOKEN_EXPIRED, eje);
79+
} catch (IllegalArgumentException iae) {
8280
logger.info("[*] case : Invalid refreshToken");
83-
throw new SecurityCustomException(SecurityErrorCode.INVALID_TOKEN);
81+
throw new SecurityCustomException(SecurityErrorCode.INVALID_TOKEN, iae);
8482
}
8583
}
8684
}
@@ -101,7 +99,7 @@ private void authenticateAccessToken(String accessToken) {
10199
null,
102100
userDetails.getAuthorities());
103101

104-
// 세션에 사용자 등록
102+
// 컨텍스트 홀더에 저장
105103
SecurityContextHolder.getContext().setAuthentication(authToken);
106104
}
107105
}

src/main/java/com/sponus/sponusbe/auth/jwt/filter/JwtExceptionFilter.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,20 @@ protected void doFilterInternal(
2525
@NonNull HttpServletRequest request,
2626
@NonNull HttpServletResponse response,
2727
@NonNull FilterChain filterChain) throws IOException {
28-
// TODO : entrypoint로 처리하도록 변경
2928
try {
3029
filterChain.doFilter(request, response);
3130
} catch (SecurityCustomException e) {
3231
log.warn(">>>>> SecurityCustomException : ", e);
3332
BaseErrorCode errorCode = e.getErrorCode();
33+
ApiResponse<String> errorResponse = ApiResponse.onFailure(
34+
errorCode.getCode(),
35+
errorCode.getMessage(),
36+
e.getMessage()
37+
);
3438
HttpResponseUtil.setErrorResponse(
3539
response,
3640
errorCode.getHttpStatus(),
37-
errorCode.getErrorResponse()
41+
errorResponse
3842
);
3943
} catch (Exception e) {
4044
log.error(">>>>> Exception : ", e);

0 commit comments

Comments
 (0)