diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 5cbb19a..e180bc1 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -9,7 +9,7 @@ name: Java CI with Gradle on: push: - branches: [ "main" ] + branches: [ "feature_4/에러-수정" ] pull_request: branches: [ "dev" ] diff --git a/src/main/java/com/example/farmusgateway/filter/JwtAuthenticationGatewayFilterFactory.java b/src/main/java/com/example/farmusgateway/filter/JwtAuthenticationGatewayFilterFactory.java index 803d1bf..d4dd1c5 100644 --- a/src/main/java/com/example/farmusgateway/filter/JwtAuthenticationGatewayFilterFactory.java +++ b/src/main/java/com/example/farmusgateway/filter/JwtAuthenticationGatewayFilterFactory.java @@ -1,6 +1,8 @@ package com.example.farmusgateway.filter; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import io.jsonwebtoken.ExpiredJwtException; import io.jsonwebtoken.JwtException; import io.jsonwebtoken.Jwts; @@ -10,14 +12,17 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; +import org.springframework.core.io.buffer.DataBuffer; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.stereotype.Component; -import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; +import java.nio.charset.StandardCharsets; + @Component @Slf4j public class JwtAuthenticationGatewayFilterFactory extends AbstractGatewayFilterFactory { @@ -30,109 +35,75 @@ public JwtAuthenticationGatewayFilterFactory() { } - // login -> token -> users (with token) -> header(include token) + @Override public GatewayFilter apply(Config config) { return (exchange, chain) -> { ServerHttpRequest request = exchange.getRequest(); + ServerHttpResponse response = exchange.getResponse(); String authorizationHeader = request.getHeaders().get(HttpHeaders.AUTHORIZATION).get(0); - log.info("authorizationHeader : {}", authorizationHeader); + log.info("authorizationHeader: {}", authorizationHeader); String jwt = authorizationHeader.replace("Bearer ", ""); - log.info("jwt : {}", jwt); + log.info("jwt: {}", jwt); - String subject = decode(jwt); - request.mutate() - .header("user", subject) - .build(); + try { + String subject = Jwts.parserBuilder().setSigningKey(secret).build() + .parseClaimsJws(jwt).getBody() + .getSubject(); - log.info("request.getURI().toString() : {}", request.getURI().toString()); + if (subject == null || subject.isEmpty()) { + return onError(response, "JWT token is not valid", HttpStatus.UNAUTHORIZED); + } - // get url after endpoint - int index = request.getURI().toString().indexOf("/api"); - String url = request.getURI().toString().substring(index); + String decodedSubject = decode(jwt); + request.mutate().header("user", decodedSubject).build(); - log.info("url : {}", url); - - if(url.equals("/api/user/reissue-token")) { - return chain.filter(exchange); - } + // get url after endpoint + int index = request.getURI().toString().indexOf("/api"); + String url = request.getURI().toString().substring(index); + log.info("url: {}", url); - if(!request.getHeaders().containsKey(HttpHeaders.AUTHORIZATION)) { - return onError(exchange, "no authorization header", HttpStatus.UNAUTHORIZED); - } + if (url.equals("/api/user/reissue-token")) { + return chain.filter(exchange); + } - if(!isJwtValid(jwt, exchange)) { - return onError(exchange, "JWT token is not valid", HttpStatus.UNAUTHORIZED); + return chain.filter(exchange); + } catch (IllegalArgumentException e) { + return onError(response, "Invalid access token header", HttpStatus.BAD_REQUEST); + } catch (io.jsonwebtoken.security.SecurityException | MalformedJwtException e) { + return onError(response, "Verification error", HttpStatus.UNAUTHORIZED); + } catch (ExpiredJwtException e) { + return onError(response, "Token expired", HttpStatus.PRECONDITION_FAILED); + } catch (JwtException e) { + return onError(response, "JWT error", HttpStatus.UNAUTHORIZED); } - - // 헤더 출력 - request.getHeaders().forEach((k, v) -> { - log.info("{} : {}", k, v); - }); - - // Custom Post Filter - return chain.filter(exchange); }; } - private boolean isJwtValid(String jwt, ServerWebExchange exchange) { - boolean returnValue = true; - - try { - String subject = Jwts.parserBuilder().setSigningKey(secret).build() - .parseClaimsJws(jwt).getBody() - .getSubject(); - - log.info("subject : {}", subject); - - if (subject == null || subject.isEmpty()) { - returnValue = false; - onError(exchange, "JWT token is not valid", HttpStatus.UNAUTHORIZED); - } - } catch (IllegalArgumentException e) { - returnValue = false; - onError(exchange, "Invalid access token header", HttpStatus.BAD_REQUEST); - } catch (io.jsonwebtoken.security.SecurityException | MalformedJwtException e) { - returnValue = false; - onError(exchange, "Verification error", HttpStatus.UNAUTHORIZED); - } catch (ExpiredJwtException e) { - returnValue = false; - onError(exchange, "Token expired", HttpStatus.PRECONDITION_FAILED); - } catch (JwtException e) { - returnValue = false; - onError(exchange, "JWT error", HttpStatus.UNAUTHORIZED); - } - - return returnValue; - } public String decode(String token) { String subject = null; - try { - subject = Jwts.parser().setSigningKey(secret) - .parseClaimsJws(token).getBody() - .getSubject(); - } catch(Exception ex) { - onError(null, "JWT error", HttpStatus.UNAUTHORIZED); - } - - if(subject == null || subject.isEmpty()) { - onError(null, "JWT error", HttpStatus.UNAUTHORIZED); - } + + subject = Jwts.parser().setSigningKey(secret) + .parseClaimsJws(token).getBody() + .getSubject(); return subject; } - // Mono, Flux -> Spring WebFlux - private Mono onError(ServerWebExchange exchange, String error, HttpStatus httpStatus) { - ServerHttpResponse response = exchange.getResponse(); - response.setStatusCode(httpStatus); + private Mono onError(ServerHttpResponse response, String message, HttpStatus status) { + + int statusCode = status.value(); // 상태 코드 가져오기 + response.setStatusCode(status); + response.getHeaders().setContentType(MediaType.APPLICATION_JSON); - log.error(error); + // JSON 포맷으로 응답 데이터 구성 + String jsonResponse = "{\"message\": \"" + message + "\", \"code\":" + statusCode + "}"; - return response.setComplete(); + DataBuffer buffer = response.bufferFactory().wrap(jsonResponse.getBytes(StandardCharsets.UTF_8)); + return response.writeWith(Mono.just(buffer)); } @Data