feat(owner-apigateway-service): access token 검증 부분 추가
- gatewayfilter 추가
This commit is contained in:
@@ -30,6 +30,8 @@ dependencies {
|
||||
implementation 'io.jsonwebtoken:jjwt:0.9.1'
|
||||
// https://mvnrepository.com/artifact/io.netty/netty-resolver-dns-native-macos
|
||||
implementation 'io.netty:netty-resolver-dns-native-macos:4.1.68.Final:osx-aarch_64'
|
||||
// https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api
|
||||
implementation 'javax.xml.bind:jaxb-api:2.3.1'
|
||||
|
||||
compileOnly 'org.projectlombok:lombok'
|
||||
developmentOnly 'org.springframework.boot:spring-boot-devtools'
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.justpickup.ownerapigatewayservice.filter;
|
||||
|
||||
import com.justpickup.ownerapigatewayservice.security.JwtTokenProvider;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilter;
|
||||
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
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;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class AuthorizationHeaderFilter extends AbstractGatewayFilterFactory<AuthorizationHeaderFilter.Config> {
|
||||
|
||||
private final JwtTokenProvider jwtTokenProvider;
|
||||
|
||||
@Autowired
|
||||
public AuthorizationHeaderFilter(JwtTokenProvider jwtTokenProvider) {
|
||||
super(Config.class);
|
||||
this.jwtTokenProvider = jwtTokenProvider;
|
||||
}
|
||||
|
||||
static class Config {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public GatewayFilter apply(Config config) {
|
||||
return (exchange, chain) -> {
|
||||
ServerHttpRequest request = exchange.getRequest();
|
||||
|
||||
HttpHeaders headers = request.getHeaders();
|
||||
if (!headers.containsKey(HttpHeaders.AUTHORIZATION)) {
|
||||
return onError(exchange, "No authorization header", HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
String authorizationHeader = headers.get(HttpHeaders.AUTHORIZATION).get(0);
|
||||
|
||||
// JWT 토큰 판별
|
||||
String token = authorizationHeader.replace("Bearer", "");
|
||||
|
||||
if (jwtTokenProvider.isExpired(token)) {
|
||||
return onError(exchange, "Access Token is Expired", HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
String subject = jwtTokenProvider.getUserId(token);
|
||||
if (subject == null) {
|
||||
return onError(exchange, "JWT token is not valid", HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
ServerHttpRequest request1 = request.mutate()
|
||||
.header("jwt-sub", subject)
|
||||
.build();
|
||||
|
||||
return chain.filter(exchange.mutate().request(request1).build());
|
||||
};
|
||||
}
|
||||
|
||||
// Mono(단일 값), Flux(다중 값) -> Spring WebFlux
|
||||
private Mono<Void> onError(ServerWebExchange exchange, String errorMsg, HttpStatus httpStatus) {
|
||||
ServerHttpResponse response = exchange.getResponse();
|
||||
response.setStatusCode(httpStatus);
|
||||
|
||||
log.error(errorMsg);
|
||||
return response.setComplete();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.justpickup.ownerapigatewayservice.security;
|
||||
|
||||
import io.jsonwebtoken.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class JwtTokenProvider {
|
||||
|
||||
@Value("${token.access-expired-time}")
|
||||
private long ACCESS_EXPIRED_TIME;
|
||||
|
||||
@Value("${token.refresh-expired-time}")
|
||||
private long REFRESH_EXPIRED_TIME;
|
||||
|
||||
@Value("${token.secret}")
|
||||
private String SECRET;
|
||||
|
||||
public String getUserId(String token) {
|
||||
return getClaimsFromJwtToken(token).getBody().getSubject();
|
||||
}
|
||||
|
||||
public boolean isExpired(String token) {
|
||||
try {
|
||||
return getClaimsFromJwtToken(token).getBody().getExpiration().before(new Date());
|
||||
} catch (ExpiredJwtException e) {
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public Jws<Claims> getClaimsFromJwtToken(String token) {
|
||||
return Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token);
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,33 @@ spring:
|
||||
- id: user-service
|
||||
uri: lb://USER-SERVICE
|
||||
predicates:
|
||||
- Path=/user-service/**
|
||||
- Path=/user-service/login
|
||||
- Method=POST
|
||||
filters:
|
||||
- RewritePath=/user-service/(?<segment>.*),/$\{segment}
|
||||
- id: user-service
|
||||
uri: lb://USER-SERVICE
|
||||
predicates:
|
||||
- Path=/user-service/refreshToken
|
||||
- Method=GET
|
||||
filters:
|
||||
- RewritePath=/user-service/(?<segment>.*),/$\{segment}
|
||||
- id: user-service
|
||||
uri: lb://USER-SERVICE
|
||||
predicates:
|
||||
- Path=/user-service/logout
|
||||
- Method=POST
|
||||
filters:
|
||||
- RewritePath=/user-service/(?<segment>.*),/$\{segment}
|
||||
- id: user-service
|
||||
uri: lb://USER-SERVICE
|
||||
predicates:
|
||||
- Path=/user-service/**
|
||||
filters:
|
||||
- AuthorizationHeaderFilter
|
||||
- RewritePath=/user-service/(?<segment>.*),/$\{segment}
|
||||
|
||||
token:
|
||||
access-expired-time: 3600000
|
||||
refresh-expired-time: 604800000
|
||||
secret: my-secret
|
||||
Reference in New Issue
Block a user