前言
前面的文章中,分別介紹了SpringCloud進階之路(十八):授權服務JdbcClientDetailsService 、SpringCloud進階之路(十九):授權服務Oauth2之JdbcTokenStore 、SpringCloud進階之路(二十):授權服務之RedisTokenStore 等實現。然而,在現如今微服務“橫行”、前後端分離的大環境下,JWT已然是業內標準。Spring Cloud Oauth2針對JWT也做了一系列封裝,滿足業務需求。本文即對Spring Cloud Oauth2的JWT實現做一系列說明。
準備工作
複用上一篇文章SpringCloud進階之路(二十):授權服務之RedisTokenStore 中的xmall-auth授權工程。
秘鑰生成
既然是採用JWT實現,那麼勢必需要提供加密演算法,分為對稱加密和非對稱加密演算法。
本文以非對稱加密演算法RSA為例,
利用JDK 1。8自帶工具keytool生成秘鑰庫,並匯出相關秘鑰檔案。
生成秘鑰庫。
keytool -genkeypair -alias xmall-auth -keyalg RSA -keypass 123456 -keystore e:\xmall-auth。jks -storepass 123456
匯出證書。
keytool -export -alias xmall-auth -keystore e:\xmall-auth。jks -file e:\pubkey。cer
列印證書。
keytool -printcert -file e:\pubkey-bin。cer
因為該匯出方式匯出的為二進位制格式證書,所以也看不出來什麼。所以,我們繼續以BASE64格式再匯出證書。
keytool -export -rfc -alias xmall-auth -keystore e:\xmall-auth。jks -file e:\pubkey-rfc。cer
列印證書。
keytool -printcert -file e:\pubkey-bin。cer
用相關軟體如EditPlus、NotePad++等開啟該證書,如下圖所示。
注意,我們匯出的是證書,而不是公鑰,不要搞混。需要公鑰資訊,還需要對證書做進一步的處理,例如使用openssl命令匯出、Java程式匯出等等,本文不再贅述
。
JWT實現改造
載入金鑰對
將前面keytool工具生成的xmall-auth。jks複製到src/main/resources下,並配置載入到程式中。
private KeyPair keyPair() { return new KeyStoreKeyFactory(new ClassPathResource(“xmall-auth。jks”), “123456”。toCharArray())。getKeyPair(“xmall-auth”, “123456”。toCharArray());}
AccessTokenConverter
建立JwtAccessTokenConverter用以配置到JwtTokenStore中。
private JwtAccessTokenConverter jwtAccessTokenConverter() { JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter(); jwtAccessTokenConverter。setKeyPair(keyPair()); return jwtAccessTokenConverter;}
JwtTokenStore
授權伺服器配置TokenStore為JwtTokenStore。
@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints。authenticationManager(authenticationManager) 。userDetailsService(userDetailsService) 。allowedTokenEndpointRequestMethods(HttpMethod。GET, HttpMethod。POST) 。accessTokenConverter(jwtAccessTokenConverter()) 。tokenStore(new JwtTokenStore(jwtAccessTokenConverter())); ;}
公鑰(token key)端點
此處最容易踩坑。前面均配置完畢,發現token key節點訪問404。一頭霧水,明明已配置好了呀。其實,還少了一項配置,即TokenKey端點。文章Spring Cloud Oauth2 token_key端點404中已詳細說明。具體配置程式碼如下。
@Beanpublic TokenKeyEndpoint tokenKeyEndpoint() { return new TokenKeyEndpoint(jwtAccessTokenConverter());}
最終配置
package com。luas。xmall。auth。configuration;import org。springframework。beans。factory。annotation。Autowired;import org。springframework。context。annotation。Bean;import org。springframework。context。annotation。Configuration;import org。springframework。core。io。ClassPathResource;import org。springframework。http。HttpMethod;import org。springframework。security。authentication。AuthenticationManager;import org。springframework。security。core。userdetails。UserDetailsService;import org。springframework。security。crypto。password。PasswordEncoder;import org。springframework。security。oauth2。config。annotation。builders。JdbcClientDetailsServiceBuilder;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。configurers。AuthorizationServerEndpointsConfigurer;import org。springframework。security。oauth2。config。annotation。web。configurers。AuthorizationServerSecurityConfigurer;import org。springframework。security。oauth2。provider。ClientDetails;import org。springframework。security。oauth2。provider。ClientDetailsService;import org。springframework。security。oauth2。provider。ClientRegistrationException;import org。springframework。security。oauth2。provider。client。JdbcClientDetailsService;import org。springframework。security。oauth2。provider。endpoint。TokenKeyEndpoint;import org。springframework。security。oauth2。provider。token。TokenStore;import org。springframework。security。oauth2。provider。token。store。*;import javax。sql。DataSource;import java。security。KeyPair;@Configuration@EnableAuthorizationServerpublic class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired private PasswordEncoder passwordEncoder; @Autowired private UserDetailsService userDetailsService; @Autowired private AuthenticationManager authenticationManager; @Autowired private DataSource dataSource; @Override public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { security。 allowFormAuthenticationForClients() 。tokenKeyAccess(“permitAll()”) 。checkTokenAccess(“permitAll()”) ; } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints。authenticationManager(authenticationManager) 。userDetailsService(userDetailsService) 。allowedTokenEndpointRequestMethods(HttpMethod。GET, HttpMethod。POST) 。accessTokenConverter(jwtAccessTokenConverter()) 。tokenStore(new JwtTokenStore(jwtAccessTokenConverter())); ; } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { // 配置方法1,只需配置DataSource即可,其它交給框架自動配置 clients。jdbc(dataSource)。passwordEncoder(passwordEncoder); } @Bean public TokenKeyEndpoint tokenKeyEndpoint() { return new TokenKeyEndpoint(jwtAccessTokenConverter()); } private JwtAccessTokenConverter jwtAccessTokenConverter() { JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter(); jwtAccessTokenConverter。setKeyPair(keyPair()); return jwtAccessTokenConverter; } private KeyPair keyPair() { return new KeyStoreKeyFactory(new ClassPathResource(“xmall-auth。jks”), “123456”。toCharArray())。getKeyPair(“xmall-auth”, “123456”。toCharArray()); }}
至此,授權伺服器改造完成。
驗證
啟動xmall-auth工程,埠7777。
訪問http://localhost:7777/oauth/token,輸入一眾引數,諸如client_id、client_secret、grant_type等,點選
Send
,即出現access_token、refresh_token等資訊。
已可以正常生成JWT。
訪問/oauth/token_key端點,亦可以正常獲取公鑰。
原始碼
github
https://github。com/liuminglei/SpringCloudLearning/tree/master/21/
gitee
https://gitee。com/xbd521/SpringCloudLearning/tree/master/21/