Skip to content

Commit e018920

Browse files
committed
[feat] 에러 처리 기능 개발 중
1 parent e19e7e6 commit e018920

File tree

9 files changed

+162
-21
lines changed

9 files changed

+162
-21
lines changed

src/main/java/Ness/Backend/domain/auth/jwt/JwtAuthorizationFilter.java

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,15 @@
33
import Ness.Backend.domain.auth.security.AuthDetailService;
44
import Ness.Backend.domain.auth.security.AuthDetails;
55
import Ness.Backend.domain.member.entity.Member;
6+
import Ness.Backend.global.error.ErrorCode;
7+
import Ness.Backend.global.error.exception.ExpiredTokenException;
8+
import Ness.Backend.global.error.exception.UnauthorizedAccessException;
9+
import Ness.Backend.global.error.exception.UnauthorizedUserException;
610
import jakarta.servlet.FilterChain;
711
import jakarta.servlet.ServletException;
812
import jakarta.servlet.http.HttpServletRequest;
913
import jakarta.servlet.http.HttpServletResponse;
14+
import lombok.extern.slf4j.Slf4j;
1015
import org.springframework.security.authentication.AuthenticationManager;
1116
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
1217
import org.springframework.security.core.Authentication;
@@ -18,6 +23,7 @@
1823
/* 사용자의 권한 부여
1924
* 요청에 포함된 JWT 토큰을 검증하고, 토큰에서 추출한 권한 정보를 기반으로 사용자에 대한 권한을 확인
2025
* 모든 사용자가 모든 리소스에 대한 권한을 가지는 것은 아님-특정 리소스에 대한 권한만 가지도록 해야 함*/
26+
@Slf4j
2127
public class JwtAuthorizationFilter extends BasicAuthenticationFilter {
2228
private JwtTokenProvider jwtTokenProvider;
2329

@@ -41,18 +47,28 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
4147

4248
/* 헤더 안의 JWT 토큰을 검증해 정상적인 사용자인지 확인 */
4349
String jwtToken = jwtHeader.substring(7);
44-
Member tokenMember = jwtTokenProvider.validJwtToken(jwtToken);
4550

46-
if(tokenMember != null){ //토큰이 정상일 경우
47-
AuthDetails authDetails = new AuthDetails(tokenMember);
51+
try {
52+
Member tokenMember = jwtTokenProvider.validJwtToken(jwtToken);
4853

49-
/* JWT 토큰 서명이 정상이면 Authentication 객체 생성 */
50-
Authentication authentication = new UsernamePasswordAuthenticationToken(authDetails, null, authDetails.getAuthorities());
54+
if(tokenMember != null){ //토큰이 정상일 경우
55+
AuthDetails authDetails = new AuthDetails(tokenMember);
5156

52-
/* 시큐리티 세션에 Authentication 을 저장 */
53-
SecurityContextHolder.getContext().setAuthentication(authentication);
57+
/* JWT 토큰 서명이 정상이면 Authentication 객체 생성 */
58+
Authentication authentication = new UsernamePasswordAuthenticationToken(authDetails, null, authDetails.getAuthorities());
5459

55-
SecurityContextHolder.getContext().setAuthentication(authentication);
60+
/* 시큐리티 세션에 Authentication 을 저장 */
61+
SecurityContextHolder.getContext().setAuthentication(authentication);
62+
}
63+
} catch (UnauthorizedAccessException e){
64+
request.setAttribute("exception", ErrorCode.UNAUTHORIZED_ACCESS.getCode());
65+
log.error("UNAUTHORIZED_ACCESS");
66+
} catch (ExpiredTokenException e){
67+
log.error("EXPIRED_TOKEN");
68+
request.setAttribute("exception", ErrorCode.EXPIRED_TOKEN.getCode());
69+
} catch (UnauthorizedUserException e){
70+
log.error("UNAUTHORIZED_USER");
71+
request.setAttribute("exception", ErrorCode.UNAUTHORIZED_USER.getCode());
5672
}
5773
chain.doFilter(request, response);
5874
}

src/main/java/Ness/Backend/domain/auth/jwt/JwtTokenProvider.java

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,15 @@
33
import Ness.Backend.domain.auth.jwt.entity.JwtToken;
44
import Ness.Backend.domain.member.MemberRepository;
55
import Ness.Backend.domain.member.entity.Member;
6+
import Ness.Backend.global.error.ErrorCode;
7+
import Ness.Backend.global.error.exception.ExpiredTokenException;
8+
import Ness.Backend.global.error.exception.UnauthorizedAccessException;
9+
import Ness.Backend.global.error.exception.UnauthorizedUserException;
610
import com.auth0.jwt.JWT;
711
import com.auth0.jwt.algorithms.Algorithm;
812
import jakarta.annotation.PostConstruct;
913
import lombok.RequiredArgsConstructor;
14+
import lombok.extern.slf4j.Slf4j;
1015
import org.springframework.beans.factory.annotation.Value;
1116
import org.springframework.web.client.HttpServerErrorException;
1217

@@ -19,6 +24,7 @@
1924

2025
/* JSON Web Token (JWT)을 생성하고 검증하는 역할 */
2126
@RequiredArgsConstructor
27+
@Slf4j
2228
public class JwtTokenProvider {
2329

2430
private final MemberRepository memberRepository;
@@ -127,21 +133,25 @@ public Member validJwtToken(String jwtToken){
127133
/* email 값이 null이 아닌지 확인 */
128134
String authKey = getAuthKeyClaim(jwtToken);
129135
if (authKey == null){ //null 값이라면 올바른 jwtToken이 아님
130-
//throw new UnauthorizedException(ErrorCode.INVALID_AUTH_TOKEN);
131-
return null;
136+
log.error("UnauthorizedAccessException");
137+
throw new UnauthorizedAccessException();
132138
}
133139

134140
/* JWT_EXPIRATION_TIME이 지나지 않았는지 확인 */
135-
Date expiresAt =getExpireTimeClaim(jwtToken);
141+
Date expiresAt = getExpireTimeClaim(jwtToken);
136142
if (!this.validExpiredTime(expiresAt)) { //만료시간이 지났다면 올바른 jwtToken이 아님
137-
//throw new UnauthorizedException(ErrorCode.EXPIRED_TOKEN);
138-
return null;
143+
log.error("ExpiredTokenException");
144+
throw new ExpiredTokenException();
139145
}
140146

141147
/* email 값이 정상적으로 있고, JWT_EXPIRATION_TIME도 지나지 않았다면,
142148
* 해당 토큰의 email 정보를 가진 맴버가 있는지 DB에서 확인 */
143-
//Member tokenUser = memberRepository.findMemberByEmail(email);
149+
Member tokenMember = memberRepository.findMemberByEmail(authKey);
150+
if (tokenMember == null) { //DB에 해당 맴버가 없다면 올바른 jwtToken이 아님
151+
log.error("UnauthorizedUserException");
152+
throw new UnauthorizedUserException();
153+
}
144154

145-
return memberRepository.findMemberByEmail(authKey);
155+
return tokenMember;
146156
}
147157
}

src/main/java/Ness/Backend/domain/auth/oAuth/OAuth2Service.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import Ness.Backend.global.auth.oAuth.naver.NaverOAuthApi;
1818
import Ness.Backend.global.auth.oAuth.naver.NaverResourceApi;
1919
import Ness.Backend.global.error.ErrorCode;
20-
import Ness.Backend.global.error.exception.UnauthorizedException;
20+
import Ness.Backend.global.error.exception.UnauthorizedAccessException;
2121
import lombok.RequiredArgsConstructor;
2222
import lombok.extern.slf4j.Slf4j;
2323
import org.springframework.core.env.Environment;
@@ -201,7 +201,7 @@ private ResourceDto getUserResource(String accessToken, String registration) {
201201
public void logout(Member member) {
202202
/* refreshToken 만료 여부 확인 */
203203
if (!refreshTokenRepository.existsById(member.getId())) {
204-
throw new UnauthorizedException(ErrorCode.INVALID_REFRESH_TOKEN);
204+
throw new UnauthorizedAccessException(ErrorCode.INVALID_REFRESH_TOKEN);
205205
}
206206

207207
refreshTokenRepository.deleteById(member.getId());
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package Ness.Backend.domain.auth.security;
2+
3+
import Ness.Backend.global.error.ErrorCode;
4+
import Ness.Backend.global.error.exception.ExpiredTokenException;
5+
import com.fasterxml.jackson.databind.ObjectMapper;
6+
import jakarta.servlet.ServletException;
7+
import jakarta.servlet.http.HttpServletRequest;
8+
import jakarta.servlet.http.HttpServletResponse;
9+
import lombok.extern.slf4j.Slf4j;
10+
import org.springframework.security.core.AuthenticationException;
11+
import org.springframework.security.web.AuthenticationEntryPoint;
12+
import org.springframework.stereotype.Component;
13+
14+
import java.io.IOException;
15+
16+
@Slf4j
17+
@Component
18+
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
19+
@Override
20+
public void commence(HttpServletRequest request,
21+
HttpServletResponse response,
22+
AuthenticationException e) throws IOException, ServletException {
23+
log.error("JwtAuthenticationEntryPoint 호출");
24+
String exception = (String)request.getAttribute("exception");
25+
response.setCharacterEncoding("utf-8");
26+
27+
if(exception.equals(ErrorCode.UNAUTHORIZED_ACCESS.getCode())) {
28+
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
29+
response.setCharacterEncoding("utf-8");
30+
response.setContentType("application/json");
31+
}
32+
else if(exception.equals(ErrorCode.EXPIRED_TOKEN.getCode())) {
33+
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
34+
response.setCharacterEncoding("utf-8");
35+
response.setContentType("application/json");
36+
ExpiredTokenException expiredTokenException = new ExpiredTokenException();
37+
ObjectMapper objectMapper = new ObjectMapper();
38+
String result = objectMapper.writeValueAsString(expiredTokenException);
39+
response.getWriter().write(result);
40+
}
41+
else if(exception.equals(ErrorCode.UNAUTHORIZED_USER.getCode())) {
42+
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
43+
response.setCharacterEncoding("utf-8");
44+
response.setContentType("application/json"); }
45+
else {
46+
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
47+
response.setCharacterEncoding("utf-8");
48+
response.setContentType("application/json");
49+
}
50+
}
51+
}

src/main/java/Ness/Backend/domain/auth/security/SecurityConfig.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public class SecurityConfig {
3030
private final AuthDetailService authDetailService;
3131
private final AuthenticationConfiguration authenticationConfiguration;
3232
private final RefreshTokenService refreshTokenService;
33+
private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
3334

3435
/* 회원가입: 패스워드 암호화를 위해 사용 */
3536
@Bean
@@ -81,6 +82,9 @@ public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Excepti
8182
.sessionManagement(c -> c.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) //세션을 생성하지 않음->토큰 기반 인증 필요
8283
.addFilter(new JwtAuthenticationFilter(authenticationManager(), jwtTokenProvider(), refreshTokenService)) //사용자 인증
8384
.addFilter(new JwtAuthorizationFilter(authenticationManager(), jwtTokenProvider(), authDetailService)) //사용자 권한 부여
85+
.exceptionHandling((exceptionConfig) ->
86+
exceptionConfig.authenticationEntryPoint(jwtAuthenticationEntryPoint)
87+
) //인가(Authorization)가 실패시 실행
8488
.authorizeHttpRequests(requests -> requests
8589
.dispatcherTypeMatchers(DispatcherType.FORWARD).permitAll()
8690
//.requestMatchers("/signup/**", "/login/**").permitAll() // 회원가입 및 로그인 경로는 인증 생략
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package Ness.Backend.global.error.exception;
2+
3+
import Ness.Backend.global.error.ErrorCode;
4+
import lombok.Getter;
5+
6+
/**
7+
* status : 400
8+
*/
9+
@Getter
10+
public class BadRequestException extends BaseException {
11+
public BadRequestException() {
12+
super(ErrorCode._BAD_REQUEST, ErrorCode._BAD_REQUEST.getMessage());
13+
}
14+
public BadRequestException(String message) {
15+
super(ErrorCode._BAD_REQUEST, message);
16+
}
17+
public BadRequestException(ErrorCode errorCode) {
18+
super(errorCode, errorCode.getMessage());
19+
}
20+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package Ness.Backend.global.error.exception;
2+
3+
import Ness.Backend.global.error.ErrorCode;
4+
import lombok.Getter;
5+
6+
/**
7+
* status : 403
8+
*/
9+
@Getter
10+
public class ExpiredTokenException extends BaseException {
11+
public ExpiredTokenException() {
12+
super(ErrorCode.EXPIRED_TOKEN, ErrorCode.EXPIRED_TOKEN.getMessage());
13+
}
14+
public ExpiredTokenException(String message) {
15+
super(ErrorCode.EXPIRED_TOKEN, message);
16+
}
17+
public ExpiredTokenException(ErrorCode errorCode) {
18+
super(errorCode, errorCode.getMessage());
19+
}
20+
}

src/main/java/Ness/Backend/global/error/exception/UnauthorizedAccessException.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@
77
* status : 401
88
*/
99
@Getter
10-
public class UnauthorizedException extends BaseException {
11-
public UnauthorizedException() {
10+
public class UnauthorizedAccessException extends BaseException {
11+
public UnauthorizedAccessException() {
1212
super(ErrorCode.UNAUTHORIZED_ACCESS, ErrorCode.UNAUTHORIZED_ACCESS.getMessage());
1313
}
14-
public UnauthorizedException(String message) {
14+
public UnauthorizedAccessException(String message) {
1515
super(ErrorCode.UNAUTHORIZED_ACCESS, message);
1616
}
17-
public UnauthorizedException(ErrorCode errorCode) {
17+
public UnauthorizedAccessException(ErrorCode errorCode) {
1818
super(errorCode, errorCode.getMessage());
1919
}
2020
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package Ness.Backend.global.error.exception;
2+
3+
import Ness.Backend.global.error.ErrorCode;
4+
import lombok.Getter;
5+
6+
/**
7+
* status : 403
8+
*/
9+
@Getter
10+
public class UnauthorizedUserException extends BaseException {
11+
public UnauthorizedUserException() {
12+
super(ErrorCode.UNAUTHORIZED_USER, ErrorCode.UNAUTHORIZED_USER.getMessage());
13+
}
14+
public UnauthorizedUserException(String message) {
15+
super(ErrorCode.UNAUTHORIZED_USER, message);
16+
}
17+
public UnauthorizedUserException(ErrorCode errorCode) {
18+
super(errorCode, errorCode.getMessage());
19+
}
20+
}

0 commit comments

Comments
 (0)