升级access_token, refresh_token为JWT(Json Web Token), 提高性能
parent
6ad88506e8
commit
d15cc67463
|
@ -0,0 +1,78 @@
|
||||||
|
package com.monkeyk.sos.config;
|
||||||
|
|
||||||
|
import com.monkeyk.sos.service.UserService;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.oauth2.provider.ClientDetailsService;
|
||||||
|
import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
|
||||||
|
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
|
||||||
|
import org.springframework.security.oauth2.provider.token.DefaultUserAuthenticationConverter;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 2020/6/9
|
||||||
|
* <p>
|
||||||
|
* <p>
|
||||||
|
* JWT TokenStore config
|
||||||
|
*
|
||||||
|
* @author Shengzhao Li
|
||||||
|
* @since 2.1.0
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@ConditionalOnProperty(name = "sos.token.store", havingValue = "jwt")
|
||||||
|
public class JWTTokenStoreConfiguration {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HMAC key, default: IH6S2dhCEMwGr7uE4fBakSuDh9SoIrRa
|
||||||
|
* alg: HMACSHA256
|
||||||
|
*/
|
||||||
|
@Value("${sos.token.store.jwt.key:IH6S2dhCEMwGr7uE4fBakSuDh9SoIrRa}")
|
||||||
|
private String jwtKey;
|
||||||
|
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public JwtAccessTokenConverter accessTokenConverter(UserService userService) {
|
||||||
|
JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
|
||||||
|
|
||||||
|
DefaultAccessTokenConverter tokenConverter = new DefaultAccessTokenConverter();
|
||||||
|
DefaultUserAuthenticationConverter userAuthenticationConverter = new DefaultUserAuthenticationConverter();
|
||||||
|
userAuthenticationConverter.setUserDetailsService(userService);
|
||||||
|
// userAuthenticationConverter.setDefaultAuthorities(new String[]{"USER"});
|
||||||
|
tokenConverter.setUserTokenConverter(userAuthenticationConverter);
|
||||||
|
|
||||||
|
tokenConverter.setIncludeGrantType(true);
|
||||||
|
// tokenConverter.setScopeAttribute("_scope");
|
||||||
|
jwtAccessTokenConverter.setAccessTokenConverter(tokenConverter);
|
||||||
|
|
||||||
|
jwtAccessTokenConverter.setSigningKey(this.jwtKey);
|
||||||
|
return jwtAccessTokenConverter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JWT TokenStore
|
||||||
|
*
|
||||||
|
* @since 2.1.0
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public TokenStore tokenStore(JwtAccessTokenConverter jwtAccessTokenConverter) {
|
||||||
|
return new JwtTokenStore(jwtAccessTokenConverter);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public DefaultTokenServices tokenServices(TokenStore tokenStore, JwtAccessTokenConverter tokenEnhancer, ClientDetailsService clientDetailsService) {
|
||||||
|
DefaultTokenServices tokenServices = new DefaultTokenServices();
|
||||||
|
tokenServices.setTokenStore(tokenStore);
|
||||||
|
tokenServices.setClientDetailsService(clientDetailsService);
|
||||||
|
//support refresh token
|
||||||
|
tokenServices.setSupportRefreshToken(true);
|
||||||
|
tokenServices.setTokenEnhancer(tokenEnhancer);
|
||||||
|
return tokenServices;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
package com.monkeyk.sos.config;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.oauth2.provider.ClientDetailsService;
|
||||||
|
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
|
||||||
|
import org.springframework.security.oauth2.provider.token.TokenStore;
|
||||||
|
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;
|
||||||
|
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 2020/6/9
|
||||||
|
* <p>
|
||||||
|
* <p>
|
||||||
|
* JDBC TokenStore config
|
||||||
|
*
|
||||||
|
* @author Shengzhao Li
|
||||||
|
* @since 2.1.0
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@ConditionalOnProperty(name = "sos.token.store", havingValue = "jdbc", matchIfMissing = true)
|
||||||
|
public class JdbcTokenStoreConfiguration {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JDBC TokenStore
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public TokenStore tokenStore(DataSource dataSource) {
|
||||||
|
return new JdbcTokenStore(dataSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public DefaultTokenServices tokenServices(TokenStore tokenStore, ClientDetailsService clientDetailsService) {
|
||||||
|
DefaultTokenServices tokenServices = new DefaultTokenServices();
|
||||||
|
tokenServices.setTokenStore(tokenStore);
|
||||||
|
tokenServices.setClientDetailsService(clientDetailsService);
|
||||||
|
//support refresh token
|
||||||
|
tokenServices.setSupportRefreshToken(true);
|
||||||
|
return tokenServices;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -26,8 +26,8 @@ import org.springframework.security.oauth2.provider.approval.UserApprovalHandler
|
||||||
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
|
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
|
||||||
import org.springframework.security.oauth2.provider.code.JdbcAuthorizationCodeServices;
|
import org.springframework.security.oauth2.provider.code.JdbcAuthorizationCodeServices;
|
||||||
import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory;
|
import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory;
|
||||||
|
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
|
||||||
import org.springframework.security.oauth2.provider.token.TokenStore;
|
import org.springframework.security.oauth2.provider.token.TokenStore;
|
||||||
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;
|
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
|
@ -116,6 +116,9 @@ public class OAuth2ServerConfiguration {
|
||||||
@Autowired
|
@Autowired
|
||||||
private TokenStore tokenStore;
|
private TokenStore tokenStore;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DefaultTokenServices tokenServices;
|
||||||
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ClientDetailsService clientDetailsService;
|
private ClientDetailsService clientDetailsService;
|
||||||
|
@ -145,13 +148,13 @@ public class OAuth2ServerConfiguration {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
// /*
|
||||||
* JDBC TokenStore
|
// * JDBC TokenStore
|
||||||
*/
|
// */
|
||||||
@Bean
|
// @Bean
|
||||||
public TokenStore tokenStore(DataSource dataSource) {
|
// public TokenStore tokenStore(DataSource dataSource) {
|
||||||
return new JdbcTokenStore(dataSource);
|
// return new JdbcTokenStore(dataSource);
|
||||||
}
|
// }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Redis TokenStore (有Redis场景时使用)
|
* Redis TokenStore (有Redis场景时使用)
|
||||||
|
@ -179,7 +182,8 @@ public class OAuth2ServerConfiguration {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
|
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
|
||||||
endpoints.tokenStore(tokenStore)
|
endpoints.tokenServices(tokenServices)
|
||||||
|
.tokenStore(tokenStore)
|
||||||
.authorizationCodeServices(authorizationCodeServices)
|
.authorizationCodeServices(authorizationCodeServices)
|
||||||
.userDetailsService(userDetailsService)
|
.userDetailsService(userDetailsService)
|
||||||
.userApprovalHandler(userApprovalHandler())
|
.userApprovalHandler(userApprovalHandler())
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
package com.monkeyk.sos.web.context;
|
package com.monkeyk.sos.web.context;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
import org.springframework.beans.factory.BeanFactory;
|
import org.springframework.beans.factory.BeanFactory;
|
||||||
import org.springframework.beans.factory.BeanFactoryAware;
|
import org.springframework.beans.factory.BeanFactoryAware;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.security.oauth2.provider.token.TokenStore;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -18,6 +22,7 @@ import org.springframework.util.Assert;
|
||||||
*/
|
*/
|
||||||
public class SOSContextHolder implements BeanFactoryAware, InitializingBean {
|
public class SOSContextHolder implements BeanFactoryAware, InitializingBean {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(SOSContextHolder.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 2.1.0
|
* @since 2.1.0
|
||||||
|
@ -25,6 +30,13 @@ public class SOSContextHolder implements BeanFactoryAware, InitializingBean {
|
||||||
private static BeanFactory beanFactory;
|
private static BeanFactory beanFactory;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 2.1.0
|
||||||
|
*/
|
||||||
|
@Value("${spring.application.name:spring-oauth-server}")
|
||||||
|
private String applicationName;
|
||||||
|
|
||||||
|
|
||||||
public SOSContextHolder() {
|
public SOSContextHolder() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,6 +81,11 @@ public class SOSContextHolder implements BeanFactoryAware, InitializingBean {
|
||||||
@Override
|
@Override
|
||||||
public void afterPropertiesSet() throws Exception {
|
public void afterPropertiesSet() throws Exception {
|
||||||
Assert.notNull(beanFactory, "beanFactory is null");
|
Assert.notNull(beanFactory, "beanFactory is null");
|
||||||
|
|
||||||
|
if (LOG.isDebugEnabled()) {
|
||||||
|
TokenStore tokenStore = getBean(TokenStore.class);
|
||||||
|
LOG.debug("{} use tokenStore: {}", this.applicationName, tokenStore);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,4 +41,10 @@ spring.main.allow-bean-definition-overriding=true
|
||||||
#spring.redis.password=
|
#spring.redis.password=
|
||||||
#spring.redis.timeout=2000
|
#spring.redis.timeout=2000
|
||||||
#spring.redis.ssl=false
|
#spring.redis.ssl=false
|
||||||
|
#
|
||||||
|
# Condition Config
|
||||||
|
# @since 2.1.0
|
||||||
|
# 配置使用什么类型 TokenStore,支持 jdbc, jwt
|
||||||
|
sos.token.store=jwt
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
package com.monkeyk.sos.config;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.security.oauth2.common.util.RandomValueStringGenerator;
|
||||||
|
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 2020/6/9
|
||||||
|
*
|
||||||
|
* @author Shengzhao Li
|
||||||
|
* @since 2.1.0
|
||||||
|
*/
|
||||||
|
public class JWTTokenStoreConfigurationTest {
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void keyTest() throws Exception {
|
||||||
|
|
||||||
|
RandomValueStringGenerator randomValueStringGenerator = new RandomValueStringGenerator(32);
|
||||||
|
String verifierKey = randomValueStringGenerator.generate();
|
||||||
|
assertNotNull(verifierKey);
|
||||||
|
// System.out.println(verifierKey);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testJwtAccessTokenConverter() throws Exception {
|
||||||
|
|
||||||
|
JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
|
||||||
|
jwtAccessTokenConverter.setSigningKey("IH6S2dhCEMwGr7uE4fBakSuDh9SoIrRa");
|
||||||
|
jwtAccessTokenConverter.afterPropertiesSet();
|
||||||
|
|
||||||
|
assertFalse(jwtAccessTokenConverter.isPublic());
|
||||||
|
Map<String, String> key = jwtAccessTokenConverter.getKey();
|
||||||
|
assertNotNull(key);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue