From ee18bb902d1d80432d68faa571162278fb5f35da Mon Sep 17 00:00:00 2001 From: wzhang Date: Sun, 13 Jan 2019 20:14:02 +0800 Subject: [PATCH] upgrade spring boot support jwk-set-uri --- README.md | 5 +++ pom.xml | 8 +++- .../AuthorizationServerConfiguration.java | 19 ++++++--- .../oauth2/server/config/JwkSetEndpoint.java | 39 +++++++++++++++++++ .../config/JwkSetEndpointConfiguration.java | 19 +++++++++ src/main/resources/application.properties | 2 +- 6 files changed, 85 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/revengemission/sso/oauth2/server/config/JwkSetEndpoint.java create mode 100644 src/main/java/com/revengemission/sso/oauth2/server/config/JwkSetEndpointConfiguration.java diff --git a/README.md b/README.md index 78b7ee2..73a3380 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,11 @@ keytool -genkey -alias jwt -keyalg RSA -keysize 1024 -keystore jwt.jks -validity ```` Get /oauth/token_key ```` +## jwk-set-uri +```` +Get /.well-known/jwks.json +```` + ## 验证token,用于在资源端调用验证token是否有效
```` Post /oauth/check_token?token=a.b.c diff --git a/pom.xml b/pom.xml index 5917866..56faa7a 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 2.1.1.RELEASE + 2.1.2.RELEASE @@ -64,6 +64,12 @@ ${spring.security.jwt.version} + + com.nimbusds + nimbus-jose-jwt + 6.5.1 + + org.thymeleaf.extras thymeleaf-extras-springsecurity5 diff --git a/src/main/java/com/revengemission/sso/oauth2/server/config/AuthorizationServerConfiguration.java b/src/main/java/com/revengemission/sso/oauth2/server/config/AuthorizationServerConfiguration.java index 641bbb4..70890b2 100644 --- a/src/main/java/com/revengemission/sso/oauth2/server/config/AuthorizationServerConfiguration.java +++ b/src/main/java/com/revengemission/sso/oauth2/server/config/AuthorizationServerConfiguration.java @@ -7,6 +7,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; import org.springframework.core.io.ClassPathResource; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.core.userdetails.UserDetailsService; @@ -14,7 +15,7 @@ import org.springframework.security.oauth2.common.OAuth2AccessToken; 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.configuration.EnableAuthorizationServer; +import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerEndpointsConfiguration; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; import org.springframework.security.oauth2.provider.OAuth2Authentication; @@ -28,13 +29,14 @@ import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory; +import javax.annotation.PostConstruct; +import java.security.KeyPair; import java.util.HashMap; import java.util.Map; +@Import(AuthorizationServerEndpointsConfiguration.class) @Configuration -@EnableAuthorizationServer public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter { - @Autowired @Qualifier("authenticationManagerBean") private AuthenticationManager authenticationManager; @@ -48,6 +50,13 @@ public class AuthorizationServerConfiguration extends AuthorizationServerConfigu @Value("${jwt.jks.keypass:keypass}") private String keypass; + KeyPair keyPair; + + @PostConstruct + public void initData() { + KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(new ClassPathResource("jwt.jks"), "keypass".toCharArray()); + this.keyPair = keyStoreKeyFactory.getKeyPair("jwt"); + } @Bean public JwtAccessTokenConverter accessTokenConverter() { @@ -70,8 +79,8 @@ public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentica } }; - KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(new ClassPathResource("jwt.jks"), keypass.toCharArray()); - accessTokenConverter.setKeyPair(keyStoreKeyFactory.getKeyPair("jwt")); + + accessTokenConverter.setKeyPair(keyPair); // 测试用,资源服务使用相同的字符达到一个对称加密的效果,生产时候使用RSA非对称加密方式 //accessTokenConverter.setSigningKey("123"); diff --git a/src/main/java/com/revengemission/sso/oauth2/server/config/JwkSetEndpoint.java b/src/main/java/com/revengemission/sso/oauth2/server/config/JwkSetEndpoint.java new file mode 100644 index 0000000..9d96243 --- /dev/null +++ b/src/main/java/com/revengemission/sso/oauth2/server/config/JwkSetEndpoint.java @@ -0,0 +1,39 @@ +package com.revengemission.sso.oauth2.server.config; + +import com.nimbusds.jose.jwk.JWKSet; +import com.nimbusds.jose.jwk.RSAKey; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.ClassPathResource; +import org.springframework.security.oauth2.provider.endpoint.FrameworkEndpoint; +import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.annotation.PostConstruct; +import java.security.KeyPair; +import java.security.Principal; +import java.security.interfaces.RSAPublicKey; +import java.util.Map; + +@FrameworkEndpoint +class JwkSetEndpoint { + + @Value("${jwt.jks.keypass:keypass}") + private String keypass; + + KeyPair keyPair; + + @PostConstruct + public void initData() { + KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(new ClassPathResource("jwt.jks"), keypass.toCharArray()); + this.keyPair = keyStoreKeyFactory.getKeyPair("jwt"); + } + + @GetMapping("/.well-known/jwks.json") + @ResponseBody + public Map getKey(Principal principal) { + RSAPublicKey publicKey = (RSAPublicKey) this.keyPair.getPublic(); + RSAKey key = new RSAKey.Builder(publicKey).build(); + return new JWKSet(key).toJSONObject(); + } +} diff --git a/src/main/java/com/revengemission/sso/oauth2/server/config/JwkSetEndpointConfiguration.java b/src/main/java/com/revengemission/sso/oauth2/server/config/JwkSetEndpointConfiguration.java new file mode 100644 index 0000000..b0f9eea --- /dev/null +++ b/src/main/java/com/revengemission/sso/oauth2/server/config/JwkSetEndpointConfiguration.java @@ -0,0 +1,19 @@ +package com.revengemission.sso.oauth2.server.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerSecurityConfiguration; + +@Configuration +class JwkSetEndpointConfiguration extends AuthorizationServerSecurityConfiguration { + @Override + protected void configure(HttpSecurity http) throws Exception { + super.configure(http); + http + .requestMatchers() + .mvcMatchers("/.well-known/jwks.json") + .and() + .authorizeRequests() + .mvcMatchers("/.well-known/jwks.json").permitAll(); + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index e539a8d..0b49726 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -3,7 +3,7 @@ server.port=10380 server.servlet.context-path=/ spring.thymeleaf.cache=false logging.level.root=info -logging.level.org.springframework.security=info +logging.level.org.springframework.security=debug logging.path=/data/logs/oauth2 logging.file.max-history=90