JWT 발행을 위한 인증 서버 수정

This commit is contained in:
assu10
2020-09-30 21:37:03 +09:00
parent c6eeb07fd4
commit 8e6a18eb00
6 changed files with 157 additions and 16 deletions

View File

@@ -48,14 +48,20 @@
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<!--<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-security</artifactId>
</dependency>
</dependency>-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-jwt</artifactId>
<version>1.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>

View File

@@ -0,0 +1,17 @@
package com.assu.cloud.authservice.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
@Component
@Configuration
public class CustomConfig {
@Value("${signing.key}")
private String jwtSigningKey = "";
public String getJwtSigningKey() {
return jwtSigningKey;
}
}

View File

@@ -8,25 +8,60 @@ import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import java.util.Arrays;
/**
* JWTTokenStoreConfig 에서 서명하고 생성한 JWT 토큰을 OAuth2 인증 서버로 연결
*
* OAuth2 인증 서버에 등록될 애플리케이션 정의
* AuthorizationServerConfigurerAdapter: 스프링 시큐리티 핵심부, 핵심 인증 인가 기능 수행하는 기본 메커니즘 제공
*/
@Configuration
public class OAuth2Config extends AuthorizationServerConfigurerAdapter {
public class JWTOAuth2Config extends AuthorizationServerConfigurerAdapter {
private final AuthenticationManager authenticationManager;
private final UserDetailsService userDetailsService;
private final TokenStore tokenStore;
private final DefaultTokenServices defaultTokenServices;
private final JwtAccessTokenConverter jwtAccessTokenConverter;
private final JWTTokenEnhancer jwtTokenEnhancer;
public OAuth2Config(AuthenticationManager authenticationManager, @Qualifier("userDetailsServiceBean") UserDetailsService userDetailsService) {
public JWTOAuth2Config(AuthenticationManager authenticationManager, @Qualifier("userDetailsServiceBean") UserDetailsService userDetailsService,
TokenStore tokenStore, DefaultTokenServices defaultTokenServices,
JwtAccessTokenConverter jwtAccessTokenConverter, JWTTokenEnhancer jwtTokenEnhancer) {
this.authenticationManager = authenticationManager;
this.userDetailsService = userDetailsService;
this.tokenStore = tokenStore;
this.defaultTokenServices = defaultTokenServices;
this.jwtAccessTokenConverter = jwtAccessTokenConverter;
this.jwtTokenEnhancer = jwtTokenEnhancer;
}
/**
* AuthorizationServerConfigurerAdapter 안에서 사용될 여러 컴포넌트 정의
* 여기선 스프링에 토큰 스토어, 액세스 토큰 컨버터, 토큰 엔헨서, 기본 인증 관리자와 사용자 상세 서비스를 이용한다고 선언
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(jwtTokenEnhancer, jwtAccessTokenConverter));
endpoints.tokenStore(tokenStore) // JWT, JWTTokenStoreConfig 에서 정의한 토큰 저장소
.accessTokenConverter(jwtAccessTokenConverter) // JWT, 스프링 시큐리티 OAuth2 JWT 사용하도록 연결
.tokenEnhancer(tokenEnhancerChain) // JWT
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService);
}
/**
* 인증 서버에 등록될 클라이언트 정의
* , OAuth2 서비스로 보호되는 서비스에 접근할 있는 클라이언트 애플리케이션 등록
* , OAuth2 서비스로 보호되는서비스에 접근할 있는 클라이언트 애플리케이션 등록
*/
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
@@ -36,14 +71,4 @@ public class OAuth2Config extends AuthorizationServerConfigurerAdapter {
.authorizedGrantTypes("refresh_token", "password", "client_credentials") // OAuth2 에서 지원하는 인가 그랜트 타입, 여기선 패스워드/클라이언트 자격증명 그랜트타입
.scopes("webclient", "mobileclient"); // 토큰 요청 애플리케이션의 수행 경계 정의
}
/**
* AuthorizationServerConfigurerAdapter 안에서 사용될 여러 컴포넌트 정의
* 여기선 스프링에 기본 인증 관리자와 사용자 상세 서비스를 이용한다고 선언
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService);
}
}

View File

@@ -0,0 +1,34 @@
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;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import java.util.HashMap;
import java.util.Map;
/**
* 액세스 토큰에 추가 정보 삽입
*/
@Configuration
public class JWTTokenEnhancer implements TokenEnhancer {
private String getUserId(String userName){
// DB 로 유저 아이디 조회
return "12345";
}
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
Map<String, Object> additionalInfo = new HashMap<>();
String userId = getUserId(authentication.getName());
additionalInfo.put("userId", userId);
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
return accessToken;
}
}

View File

@@ -0,0 +1,59 @@
package com.assu.cloud.authservice.security;
import com.assu.cloud.authservice.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.TokenEnhancer;
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;
/**
* 인증 서버가 JWT 토큰을 생성, 서명, 해석하는 방법 지정
*/
@Configuration
public class JWTTokenStoreConfig {
private final CustomConfig customConfig;
public JWTTokenStoreConfig(CustomConfig customConfig) {
this.customConfig = customConfig;
}
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(jwtAccessTokenConverter());
}
/**
* 서비스에 전달된 토큰에서 데이터를 읽는데 사용
* @return
*/
@Bean
@Primary // 특정 타입의 빈이 둘 이상인 경우 (여기선 DefaultTokenServices) @Primary 로 지정된 타입을 자동 주입
public DefaultTokenServices tokenServices() {
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
defaultTokenServices.setSupportRefreshToken(true);
return defaultTokenServices;
}
/**
* JWT 와 OAuth2 인증 서버 사이의 변환기
* 토큰 서명에 사용되는 서명키 사용 (여기선 대칭 키)
* @return
*/
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(customConfig.getJwtSigningKey()); // 토큰 서명에 사용되는 서명키 정의
return converter;
}
@Bean
public TokenEnhancer jwtTokenEnhancer() {
return new JWTTokenEnhancer();
}
}

View File

@@ -8,7 +8,7 @@ spring:
uri: https://github.com/assu10/config-repo.git
username: assu10
password: '{cipher}f38ff3546220bbac52d81c132916b1b1fd7c3cfdcfdf408760d1c4bf0b4ee97c'
search-paths: member-service, event-service, eurekaserver, zuulserver # 구성 파일을 찾을 폴더 경로
search-paths: member-service, event-service, eurekaserver, zuulserver, auth-service # 구성 파일을 찾을 폴더 경로
encrypt:
enabled: false