Skip to content

Commit

Permalink
#31 [Update] jwt 토큰 예외처리 구현 완료
Browse files Browse the repository at this point in the history
  • Loading branch information
Anna-Jin committed Jul 15, 2022
1 parent 1a00f65 commit 0040a77
Show file tree
Hide file tree
Showing 9 changed files with 60 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public static <T> AuthResponse<T> success(String name, T body) {
ErrorCode.SUCCESS_MESSAGE.getMessage()), map);
}

// 이 밑에 코드는 전부 exception 으로 빼기
public static <T> AuthResponse<T> fail() {
return new AuthResponse<>(new AuthResponseHeader(
ErrorCode.FAILED_MESSAGE.getCode(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
@Setter
@AllArgsConstructor
public class AuthResponseHeader {
private int code;
private String code;
private String message;
}
25 changes: 14 additions & 11 deletions src/main/java/com/mpnp/baechelin/oauth/exception/ErrorCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,20 @@
@RequiredArgsConstructor
public enum ErrorCode {

SUCCESS_MESSAGE(200, "SUCCESS"),
NOT_FOUND_MESSAGE(500, "NOT FOUND"),
FAILED_MESSAGE(500, "서버에서 오류가 발생하였습니다."),
INVALID_ACCESS_TOKEN(401, "유효하지 않은 Access Token입니다."),
INVALID_REFRESH_TOKEN(401, "유효하지 않은 Refresh Token입니다."),
NOT_EXPIRED_TOKEN_YET(401,"만료되지 않은 JWT 토큰입니다."),
EXPIRED_TOKEN(401, "만료된 JWT 토큰입니다."),
WRONG_TYPE_TOKEN(401, "잘못된 JWT 토큰입니다."),
ACCESS_DENIED(401, "접근이 거부되었습니다."),
ALREADY_LOGIN_ACCOUNT(400, "ALREADY_LOGIN_ACCOUNT");
SUCCESS_MESSAGE(200, "S-SUC200","SUCCESS"),
// NOT_FOUND_MESSAGE(500, "BE001", "NOT FOUND"),
FAILED_MESSAGE(500, "E-FAI500","서버에서 오류가 발생하였습니다."),
INVALID_ACCESS_TOKEN(401, "E-IAT401","유효하지 않은 Access Token입니다."),
INVALID_REFRESH_TOKEN(401, "E-IRT401", "유효하지 않은 Refresh Token입니다."),
NOT_EXPIRED_TOKEN_YET(401, "E-NET401", "만료되지 않은 JWT 토큰입니다."),
EXPIRED_TOKEN(401, "E-EXT401", "만료된 JWT 토큰입니다."),
WRONG_TYPE_TOKEN(401, "E-WTT401","잘못된 JWT 토큰입니다."),
WRONG_TYPE_SIGNATURE(401, "E-WTS401", "잘못된 JWT 서명입니다."),
ACCESS_DENIED(401, "E-ACD401","접근이 거부되었습니다."),
TOKEN_NOT_EXIST(401, "E-TNE401", "토큰이 존재하지 않습니다."),
ALREADY_LOGIN_ACCOUNT(400, "E-ALA400","다른 계정으로 로그인 되었습니다.");

private final int code;
private final int status;
private final String code;
private final String message;
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public void commence(
HttpServletResponse response,
AuthenticationException authException
) throws IOException {
String exception = (String)request.getAttribute("javax.servlet.error.exception");
String exception = (String)request.getAttribute("exception");

if(exception == null) {
setResponse(response, ErrorCode.FAILED_MESSAGE);
Expand All @@ -29,12 +29,15 @@ public void commence(
else if(exception.equals(ErrorCode.WRONG_TYPE_TOKEN.getCode())) {
setResponse(response, ErrorCode.WRONG_TYPE_TOKEN);
}
else if(exception.equals(ErrorCode.WRONG_TYPE_SIGNATURE.getCode())) {
setResponse(response, ErrorCode.WRONG_TYPE_SIGNATURE);
}
//토큰 만료된 경우
else if(exception.equals(ErrorCode.EXPIRED_TOKEN.getCode())) {
setResponse(response, ErrorCode.EXPIRED_TOKEN);
}
else {
setResponse(response, ErrorCode.ACCESS_DENIED);
setResponse(response, ErrorCode.TOKEN_NOT_EXIST);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package com.mpnp.baechelin.oauth.filter;

import com.mpnp.baechelin.oauth.exception.ErrorCode;
import com.mpnp.baechelin.oauth.token.AuthToken;
import com.mpnp.baechelin.oauth.token.AuthTokenProvider;
import com.mpnp.baechelin.util.HeaderUtil;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.UnsupportedJwtException;
import io.jsonwebtoken.security.SignatureException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
Expand Down Expand Up @@ -37,11 +41,27 @@ protected void doFilterInternal(
// String으로 된 token을 AuthToken객체로 변환해준다.
AuthToken token = tokenProvider.convertAuthToken(tokenStr);

if (token.validate()) {
// 토큰이 유효하다면 인증 객체 생성
Authentication authentication = tokenProvider.getAuthentication(token);
// SecurityContextHolder 에 인증 객체를 넣는다.
SecurityContextHolder.getContext().setAuthentication(authentication);
try {
if (token != null && token.tokenValidate()) {
Authentication authentication = tokenProvider.getAuthentication(token);
// SecurityContextHolder 에 인증 객체를 넣는다.
SecurityContextHolder.getContext().setAuthentication(authentication);
}
} catch (SignatureException e) {
log.info("잘못된 JWT 서명입니다.");
request.setAttribute("exception", ErrorCode.WRONG_TYPE_SIGNATURE.getCode());
} catch (MalformedJwtException e) {
log.info("유효하지 않은 구성의 JWT 토큰입니다.");
request.setAttribute("exception", ErrorCode.WRONG_TYPE_TOKEN.getCode());
} catch (ExpiredJwtException e) {
log.info("만료된 JWT 토큰입니다.");
request.setAttribute("exception", ErrorCode.EXPIRED_TOKEN.getCode());
} catch (UnsupportedJwtException e) {
log.info("지원되지 않는 형식이나 구성의 JWT 토큰입니다.");
request.setAttribute("exception", ErrorCode.WRONG_TYPE_TOKEN.getCode());
} catch (IllegalArgumentException e) {
log.info(e.toString().split(":")[1].trim());
request.setAttribute("exception", ErrorCode.TOKEN_NOT_EXIST.getCode());
}

filterChain.doFilter(request, response);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ protected String determineTargetUrl(HttpServletRequest request, HttpServletRespo
userRefreshTokenRepository.saveAndFlush(userRefreshToken);
}

// 쿠키 만료시간 = 리프레시 토큰 만료시간
int cookieMaxAge = (int) refreshTokenExpiry / 60;

// 기존에 cookie에 들어있는 refresh token을 삭제하고 다시 저장한다.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class OAuth2AuthorizationRequestBasedOnCookieRepository implements Author
public final static String OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME = "oauth2_auth_request";
public final static String REDIRECT_URI_PARAM_COOKIE_NAME = "redirect_uri";
public final static String REFRESH_TOKEN ="refresh_token";
private final static int cookieExpireSecondes = 180;
private final static int cookieExpireSeconds = 180;

// cookie의 request를 가져오는 로직
@Override
Expand All @@ -37,11 +37,11 @@ public void saveAuthorizationRequest(OAuth2AuthorizationRequest authorizationReq
return;
}

CookieUtil.addCookie(response, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME, CookieUtil.serialize(authorizationRequest), cookieExpireSecondes);
CookieUtil.addCookie(response, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME, CookieUtil.serialize(authorizationRequest), cookieExpireSeconds);
String redirectUriAfterLogin = request.getParameter(REDIRECT_URI_PARAM_COOKIE_NAME);

if (StringUtils.isNotBlank(redirectUriAfterLogin)) {
CookieUtil.addCookie(response, REDIRECT_URI_PARAM_COOKIE_NAME, redirectUriAfterLogin, cookieExpireSecondes);
CookieUtil.addCookie(response, REDIRECT_URI_PARAM_COOKIE_NAME, redirectUriAfterLogin, cookieExpireSeconds);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ private OAuth2User process(OAuth2UserRequest userRequest, OAuth2User user) {
if (savedUser != null) {
// DB에 유저 정보가 있을 때
if (providerType != savedUser.getProviderType()) {
throw new OAuthProviderMissMatchException(ErrorCode.ALREADY_LOGIN_ACCOUNT.getMessage());
throw new OAuthProviderMissMatchException(ErrorCode.ALREADY_LOGIN_ACCOUNT.getCode() + "=" + providerType);
}
updateUser(savedUser, userInfo);
} else {
Expand Down
9 changes: 9 additions & 0 deletions src/main/java/com/mpnp/baechelin/oauth/token/AuthToken.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,15 @@ public boolean validate() {
return this.getTokenClaims() != null;
}

public boolean tokenValidate() {
Jws<Claims> claimsJws = Jwts.parserBuilder()
.setSigningKey(key)
.build()
.parseClaimsJws(token);
return !claimsJws.getBody().isEmpty();
}


// 토큰의 claims, payload 값 가져오기
public Claims getTokenClaims() {
try {
Expand Down

0 comments on commit 0040a77

Please sign in to comment.