SpringCloud進階之路(二十一):授權服務JWT實現JwtTokenStore

前言

前面的文章中,分別介紹了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

SpringCloud進階之路(二十一):授權服務JWT實現JwtTokenStore

匯出證書。

keytool -export -alias xmall-auth -keystore e:\xmall-auth。jks -file e:\pubkey。cer

SpringCloud進階之路(二十一):授權服務JWT實現JwtTokenStore

列印證書。

keytool -printcert -file e:\pubkey-bin。cer

SpringCloud進階之路(二十一):授權服務JWT實現JwtTokenStore

因為該匯出方式匯出的為二進位制格式證書,所以也看不出來什麼。所以,我們繼續以BASE64格式再匯出證書。

keytool -export -rfc -alias xmall-auth -keystore e:\xmall-auth。jks -file e:\pubkey-rfc。cer

SpringCloud進階之路(二十一):授權服務JWT實現JwtTokenStore

列印證書。

keytool -printcert -file e:\pubkey-bin。cer

SpringCloud進階之路(二十一):授權服務JWT實現JwtTokenStore

用相關軟體如EditPlus、NotePad++等開啟該證書,如下圖所示。

SpringCloud進階之路(二十一):授權服務JWT實現JwtTokenStore

注意,我們匯出的是證書,而不是公鑰,不要搞混。需要公鑰資訊,還需要對證書做進一步的處理,例如使用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等資訊。

SpringCloud進階之路(二十一):授權服務JWT實現JwtTokenStore

已可以正常生成JWT。

訪問/oauth/token_key端點,亦可以正常獲取公鑰。

SpringCloud進階之路(二十一):授權服務JWT實現JwtTokenStore

原始碼

github

https://github。com/liuminglei/SpringCloudLearning/tree/master/21/

gitee

https://gitee。com/xbd521/SpringCloudLearning/tree/master/21/