搭建過程可以分為以下幾步
- 構建簡單的Spring Security + OAuth2.0 認證服務
- 優化認證服務(使用JWT技術加強token,自定義auth接口以及返回結果)
- 配置gateway服務完成簡單鑒權功能
- 優化gateway配置(添加復雜鑒權邏輯等等)
(二)優化認證服務
在上一篇中已經介紹了如何搭建簡單的認證服務。但在該簡單框架中,token雖然可生成可刷新,但是它並沒有和用戶信息掛鈎,無法用於驗證。
在本篇中將會使用JWT加強token,驗證時可以直接解析token獲取其中信息。
一. 使用JWT加強Token
使用keytool 生成RSA證書jwt.jks,復制到resource目錄下
mac系統下,使用該命令查看Java安裝目錄
/usr/libexec/java_home -V
進入Java安裝目錄下的bin目錄,生成 RSA 證書,生成過程中需要填寫密碼等一系列信息
keytool -genkey -alias jwt -keyalg RSA -keystore jwt.jks
將生成的文件復制到resource目錄下
在之前基礎上,修改OAuth配置文件 OAuth2ServerConfig,讀取RSA證書信息,並配置好轉換JWT Token
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager)
.userDetailsService(userService)
// 設置token轉換器
.accessTokenConverter(accessTokenConverter());
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setKeyPair(keyPair());
return converter;
}
@Bean
public KeyPair keyPair() {
// 這里的password需要與之前創建時輸入的一致,否則會無法讀取導致服務啟動失敗
KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(new ClassPathResource("jwt.jks"), "password".toCharArray());
return keyStoreKeyFactory.getKeyPair("jwt");
}
再次啟動服務進行測試,發現生成的Token已經變為了JWT Token
使用在線解析可以看到JWT Token中包含的內容
二. JWT中添加自定義字段
生成JWT Token后,可能需要進行擴展,在其中添加一些自定義字段。
實現TokenEnhancer接口進行內容增強,例如在Token中添加userId字段.
@Service
public class JwtTokenEnhancer implements TokenEnhancer {
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken oAuth2AccessToken, OAuth2Authentication oAuth2Authentication) {
Map<String, Object> additionalInfo = new HashMap<>();
SecurityUser user = (SecurityUser) oAuth2Authentication.getPrincipal();
additionalInfo.put("userId", user.getId());
((DefaultOAuth2AccessToken) oAuth2AccessToken).setAdditionalInformation(additionalInfo);
return oAuth2AccessToken;
}
}
在config中配置該Enhancer
@Autowired
private JwtTokenEnhancer jwtTokenEnhancer;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager)
.userDetailsService(userService)
.accessTokenConverter(accessTokenConverter());
// 將兩個增強器連起來
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(jwtTokenEnhancer, accessTokenConverter()));
endpoints.tokenEnhancer(tokenEnhancerChain);
}
啟動服務進行測試,發現生成的JWT Token帶上了自定義的信息
三. 自定義oauth/token 返回數據結構
SpringSecurity提供的auth接口如下
故只需要自定義認證接口,在接口內調用該函數,將返回的OAuth2AccessToken包裝為自定義的數據結構即可
具體地,定義返回數據結構
@Data
@Builder
public class TokenDTO {
private String token;
private String refreshToken;
private String tokenHead;
}
自定義認證接口如下
@RestController
@RequestMapping("/oauth")
public class AuthController {
@Autowired
private TokenEndpoint tokenEndpoint;
@PostMapping(value = "/token")
public CommonResult<TokenDTO> postAccessToken(Principal principal, @RequestParam Map<String, String> parameters) throws HttpRequestMethodNotSupportedException {
OAuth2AccessToken oAuth2AccessToken = tokenEndpoint.postAccessToken(principal, parameters).getBody();
TokenDTO tokenDTO = TokenDTO.builder().token(oAuth2AccessToken.getValue())
.refreshToken(oAuth2AccessToken.getRefreshToken().getValue())
.tokenHead("Bearer ").build();
return CommonResult.success(tokenDTO);
}
}
啟動服務進行測試,返回了自定義的數據結構
Spring Security + OAuth2.0 構建微服務統一認證解決方案(一)
Spring Security + OAuth2.0 構建微服務統一認證解決方案(三)