diff --git a/auth-service/src/main/java/com/assu/cloud/authservice/security/JWTOAuth2Config.java b/auth-service/src/main/java/com/assu/cloud/authservice/security/JWTOAuth2Config.java
index 79dcdcb..b2bffcc 100644
--- a/auth-service/src/main/java/com/assu/cloud/authservice/security/JWTOAuth2Config.java
+++ b/auth-service/src/main/java/com/assu/cloud/authservice/security/JWTOAuth2Config.java
@@ -49,12 +49,13 @@ public class JWTOAuth2Config extends AuthorizationServerConfigurerAdapter {
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
+ // 스프링 OAuth 의 TokenEnhancerChain 를 등록하면 여러 TokenEnhancer 후킹 가능
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(jwtTokenEnhancer, jwtAccessTokenConverter));
endpoints.tokenStore(tokenStore) // JWT, JWTTokenStoreConfig 에서 정의한 토큰 저장소
.accessTokenConverter(jwtAccessTokenConverter) // JWT, 스프링 시큐리티 OAuth2 가 JWT 사용하도록 연결
- .tokenEnhancer(tokenEnhancerChain) // JWT
+ .tokenEnhancer(tokenEnhancerChain) // JWT, endpoints 에 tokenEnhancerChain 연결
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService);
}
diff --git a/auth-service/src/main/java/com/assu/cloud/authservice/security/JWTTokenEnhancer.java b/auth-service/src/main/java/com/assu/cloud/authservice/security/JWTTokenEnhancer.java
index f06c869..bdc941f 100644
--- a/auth-service/src/main/java/com/assu/cloud/authservice/security/JWTTokenEnhancer.java
+++ b/auth-service/src/main/java/com/assu/cloud/authservice/security/JWTTokenEnhancer.java
@@ -1,6 +1,5 @@
package com.assu.cloud.authservice.security;
-import com.assu.cloud.authservice.config.CustomConfig;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
@@ -28,6 +27,7 @@ public class JWTTokenEnhancer implements TokenEnhancer {
additionalInfo.put("userId", userId);
+ // 모든 추가 속성은 HashMap 에 추가하고, 메서드에 전달된 accessToken 변수에 추가
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
return accessToken;
}
diff --git a/auth-service/src/main/java/com/assu/cloud/authservice/security/JWTTokenStoreConfig.java b/auth-service/src/main/java/com/assu/cloud/authservice/security/JWTTokenStoreConfig.java
index fcf4a4a..d9ae9e1 100644
--- a/auth-service/src/main/java/com/assu/cloud/authservice/security/JWTTokenStoreConfig.java
+++ b/auth-service/src/main/java/com/assu/cloud/authservice/security/JWTTokenStoreConfig.java
@@ -52,6 +52,11 @@ public class JWTTokenStoreConfig {
return converter;
}
+ /**
+ * OAuth2 에 JWT 토큰 확장 클래스인 JWTTokenEnhancer 클래스를 사용한다고 알리기 위해 빈으로 노출
+ * 여기서 노출하면 JWTOAuth2Config 에서 사용 가능
+ * @return
+ */
@Bean
public TokenEnhancer jwtTokenEnhancer() {
return new JWTTokenEnhancer();
diff --git a/event-service/pom.xml b/event-service/pom.xml
index 368a199..ce128fb 100644
--- a/event-service/pom.xml
+++ b/event-service/pom.xml
@@ -61,6 +61,12 @@
spring-security-oauth2-autoconfigure
+
+ org.springframework.security
+ spring-security-jwt
+ 1.1.1.RELEASE
+
+
org.springframework.boot
spring-boot-starter-test
diff --git a/event-service/src/main/java/com/assu/cloud/eventservice/EventServiceApplication.java b/event-service/src/main/java/com/assu/cloud/eventservice/EventServiceApplication.java
index ac650d9..2536a0b 100644
--- a/event-service/src/main/java/com/assu/cloud/eventservice/EventServiceApplication.java
+++ b/event-service/src/main/java/com/assu/cloud/eventservice/EventServiceApplication.java
@@ -4,11 +4,14 @@ import com.assu.cloud.eventservice.utils.CustomContextInterceptor;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoRestTemplateFactory;
+import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Primary;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
+import org.springframework.web.client.RestTemplate;
import java.util.Collections;
import java.util.List;
@@ -16,9 +19,32 @@ import java.util.List;
@EnableEurekaClient
@SpringBootApplication
@EnableFeignClients
-@EnableResourceServer
+@EnableResourceServer // 보호 자원으로 설정
public class EventServiceApplication {
+ /**
+ * 사용자 정의 RestTemplate 빈을 생성하여 토큰 삽입
+ * RestTemplate 기반 호출이 수행되기 전 후킹되는 메서드
+ */
+ @Primary
+ @LoadBalanced
+ @Bean
+ public RestTemplate getCustomRestTemplate() {
+ RestTemplate template = new RestTemplate();
+ List interceptors = template.getInterceptors();
+
+ // CustomContextInterceptor 는 Authorization 헤더를 모든 REST 호출에 삽입함
+ if (interceptors == null) {
+ template.setInterceptors(Collections.singletonList(new CustomContextInterceptor()));
+ } else {
+ interceptors.add(new CustomContextInterceptor());
+ template.setInterceptors(interceptors);
+ }
+ return template;
+ }
+
+ /*
+ // OAuth2 RestTemplate -> JWT 기반 토큰을 전파하지 앟음
//@LoadBalanced
@Bean
public OAuth2RestTemplate restTemplate(UserInfoRestTemplateFactory factory) {
@@ -31,9 +57,11 @@ public class EventServiceApplication {
factory.getUserInfoRestTemplate().setInterceptors(interceptors);
}
return factory.getUserInfoRestTemplate();
- }
+ }*/
- /*@LoadBalanced // 스프링 클라우드가 리본이 지원하는 RestTemplate 클래스 생성하도록 지시
+ /*
+ 기본 RestTemplate
+ @LoadBalanced // 스프링 클라우드가 리본이 지원하는 RestTemplate 클래스 생성하도록 지시
@Bean
public RestTemplate getRestTemplate() {
// return new RestTemplate();
diff --git a/event-service/src/main/java/com/assu/cloud/eventservice/client/MemberRestTemplateClient.java b/event-service/src/main/java/com/assu/cloud/eventservice/client/MemberRestTemplateClient.java
index f2ad1e0..9fec1e5 100644
--- a/event-service/src/main/java/com/assu/cloud/eventservice/client/MemberRestTemplateClient.java
+++ b/event-service/src/main/java/com/assu/cloud/eventservice/client/MemberRestTemplateClient.java
@@ -12,7 +12,7 @@ import org.springframework.stereotype.Component;
@Component
public class MemberRestTemplateClient {
- private final OAuth2RestTemplate restTemplate;
+ /*private final OAuth2RestTemplate restTemplate;
private final CustomConfig customConfig;
public MemberRestTemplateClient(OAuth2RestTemplate restTemplate, CustomConfig customConfig) {
@@ -36,5 +36,5 @@ public class MemberRestTemplateClient {
);
return restExchange.getBody();
- }
+ }*/
}
diff --git a/event-service/src/main/java/com/assu/cloud/eventservice/config/CustomConfig.java b/event-service/src/main/java/com/assu/cloud/eventservice/config/CustomConfig.java
index 9bc63d8..52803d7 100644
--- a/event-service/src/main/java/com/assu/cloud/eventservice/config/CustomConfig.java
+++ b/event-service/src/main/java/com/assu/cloud/eventservice/config/CustomConfig.java
@@ -13,6 +13,9 @@ public class CustomConfig {
@Value("${service.id.zuul}")
private String serviceIdZuul;
+ @Value("${signing.key}")
+ private String jwtSigningKey = "";
+
public String getYourName() {
return yourName;
}
@@ -20,4 +23,8 @@ public class CustomConfig {
public String getServiceIdZuul() {
return serviceIdZuul;
}
+
+ public String getJwtSigningKey() {
+ return jwtSigningKey;
+ }
}
diff --git a/event-service/src/main/java/com/assu/cloud/eventservice/controller/EventController.java b/event-service/src/main/java/com/assu/cloud/eventservice/controller/EventController.java
index 1b58a05..aaede61 100644
--- a/event-service/src/main/java/com/assu/cloud/eventservice/controller/EventController.java
+++ b/event-service/src/main/java/com/assu/cloud/eventservice/controller/EventController.java
@@ -49,8 +49,8 @@ public class EventController {
return "[EVENT] Gift is " + gift;
}
- @GetMapping("userInfo/{name}")
+ /*@GetMapping("userInfo/{name}")
public String userInfo(@PathVariable("name") String name) {
return "[EVENT-MEMBER] " + memberRestTemplateClient.userInfo(name);
- }
+ }*/
}
diff --git a/event-service/src/main/java/com/assu/cloud/eventservice/security/JWTTokenStoreConfig.java b/event-service/src/main/java/com/assu/cloud/eventservice/security/JWTTokenStoreConfig.java
new file mode 100644
index 0000000..0c83cb1
--- /dev/null
+++ b/event-service/src/main/java/com/assu/cloud/eventservice/security/JWTTokenStoreConfig.java
@@ -0,0 +1,41 @@
+package com.assu.cloud.eventservice.security;
+
+import com.assu.cloud.eventservice.config.CustomConfig;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
+import org.springframework.security.oauth2.provider.token.TokenStore;
+import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
+import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
+
+@Configuration
+public class JWTTokenStoreConfig {
+
+ private final CustomConfig customConfig;
+
+ public JWTTokenStoreConfig(CustomConfig customConfig) {
+ this.customConfig = customConfig;
+ }
+
+ @Bean
+ public TokenStore tokenStore() {
+ return new JwtTokenStore(jwtAccessTokenConverter());
+ }
+
+ @Bean
+ public JwtAccessTokenConverter jwtAccessTokenConverter() {
+ JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
+ converter.setSigningKey(customConfig.getJwtSigningKey());
+ return converter;
+ }
+
+ @Bean
+ @Primary
+ public DefaultTokenServices tokenServices() {
+ DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
+ defaultTokenServices.setTokenStore(tokenStore());
+ defaultTokenServices.setSupportRefreshToken(true);
+ return defaultTokenServices;
+ }
+}
diff --git a/event-service/src/main/java/com/assu/cloud/eventservice/utils/CustomContext.java b/event-service/src/main/java/com/assu/cloud/eventservice/utils/CustomContext.java
index 58724d7..1daae93 100644
--- a/event-service/src/main/java/com/assu/cloud/eventservice/utils/CustomContext.java
+++ b/event-service/src/main/java/com/assu/cloud/eventservice/utils/CustomContext.java
@@ -9,11 +9,14 @@ import org.springframework.stereotype.Component;
@Component
public class CustomContext {
public static final String CORRELATION_ID = "assu-correlation-id";
+ public static final String AUTH_TOKEN = "Authorization";
private static final ThreadLocal correlationId = new ThreadLocal<>();
+ private static final ThreadLocal authToken = new ThreadLocal<>();
// 그 외 필요한 항목 넣을 수 있음 (인증 토큰 등...)
+
public static String getCorrelationId() {
return correlationId.get();
}
@@ -21,4 +24,12 @@ public class CustomContext {
public static void setCorrelationId(String cid) {
correlationId.set(cid);
}
+
+ public static String getAuthToken() {
+ return authToken.get();
+ }
+
+ public static void setAuthToken(String aToken) {
+ authToken.set(aToken);
+ }
}
diff --git a/event-service/src/main/java/com/assu/cloud/eventservice/utils/CustomContextFilter.java b/event-service/src/main/java/com/assu/cloud/eventservice/utils/CustomContextFilter.java
index c9a5803..c427eab 100644
--- a/event-service/src/main/java/com/assu/cloud/eventservice/utils/CustomContextFilter.java
+++ b/event-service/src/main/java/com/assu/cloud/eventservice/utils/CustomContextFilter.java
@@ -12,6 +12,8 @@ import java.io.IOException;
* 유입되는 HTTP 요청을 가로채서 필요한 헤더값을 CustomContext 에 매핑
*
* REST 서비스에 대한 모든 HTTP 요청을 가로채서 컨텍스트 정보(상관관계 ID 등)를 추출해 CustomContext 클래스에 매핑하는 HTTP 서블릿 필터
+ * (즉, HTTP 헤더에서 인증 토큰과 상관관계 ID 파싱)
+ *
* REST 서비스 호출 시 코드에서 CustomContext 액세스가 필요할 때마다 ThreadLocal 변수에서 검색해 읽어올 수 있음
*/
@Component
@@ -25,7 +27,9 @@ public class CustomContextFilter implements Filter {
// HTTP 호출 헤더에서 상관관계 ID 를 검색하여 CustomContextHolder 의 CustomContext 클래스에 설정
CustomContextHolder.getContext().setCorrelationId(httpServletRequest.getHeader(CustomContext.CORRELATION_ID));
+
// 그 외 필요한 항목 넣을 수 있음 (인증 토큰 등...)
+ CustomContextHolder.getContext().setAuthToken(httpServletRequest.getHeader(CustomContext.AUTH_TOKEN));
logger.debug("상관관계 ID {} 로 실행된 동적 라우팅", CustomContextHolder.getContext().getCorrelationId());
diff --git a/event-service/src/main/java/com/assu/cloud/eventservice/utils/CustomContextHolder.java b/event-service/src/main/java/com/assu/cloud/eventservice/utils/CustomContextHolder.java
index fa17cb8..3e3562b 100644
--- a/event-service/src/main/java/com/assu/cloud/eventservice/utils/CustomContextHolder.java
+++ b/event-service/src/main/java/com/assu/cloud/eventservice/utils/CustomContextHolder.java
@@ -27,7 +27,7 @@ public class CustomContextHolder {
}
public static final void setContext(CustomContext ctx) {
- Assert.notNull(ctx, "customcontxt is null.");
+ Assert.notNull(ctx, "CustomContext is null.");
customContext.set(ctx);
}
diff --git a/event-service/src/main/java/com/assu/cloud/eventservice/utils/CustomContextInterceptor.java b/event-service/src/main/java/com/assu/cloud/eventservice/utils/CustomContextInterceptor.java
index cf4e4bf..321b8c4 100644
--- a/event-service/src/main/java/com/assu/cloud/eventservice/utils/CustomContextInterceptor.java
+++ b/event-service/src/main/java/com/assu/cloud/eventservice/utils/CustomContextInterceptor.java
@@ -9,7 +9,7 @@ import org.springframework.http.client.ClientHttpResponse;
import java.io.IOException;
/**
- * RestTemplate 인스턴스에서 실행되는 모든 HTTP 기반 서비스 발신 요청에 상관관계 ID 삽입
+ * RestTemplate 인스턴스에서 실행되는 모든 HTTP 기반 서비스 발신 요청에 상관관계 ID 삽입 + 토큰
*/
public class CustomContextInterceptor implements ClientHttpRequestInterceptor {
/**
@@ -20,7 +20,9 @@ public class CustomContextInterceptor implements ClientHttpRequestInterceptor {
HttpHeaders headers = httpRequest.getHeaders();
headers.add(CustomContext.CORRELATION_ID, CustomContextHolder.getContext().getCorrelationId());
+
// 그 외 필요한 항목 넣을 수 있음 (인증 토큰 등...)
+ headers.add(CustomContext.AUTH_TOKEN, CustomContextHolder.getContext().getAuthToken()); // HTTP 헤더에 인증 토큰 추가
return clientHttpRequestExecution.execute(httpRequest, bytes);
}
diff --git a/event-service/src/main/resources/application.yaml b/event-service/src/main/resources/application.yaml
index a74ec55..3fdae5b 100644
--- a/event-service/src/main/resources/application.yaml
+++ b/event-service/src/main/resources/application.yaml
@@ -1,2 +1,2 @@
server:
- port: 8070
+ port: 8070
\ No newline at end of file