Spring Security + OAuth2.0 構建微服務統一認證解決方案(二)


搭建過程可以分為以下幾步

  1. 構建簡單的Spring Security + OAuth2.0 認證服務
  2. 優化認證服務(使用JWT技術加強token,自定義auth接口以及返回結果)
  3. 配置gateway服務完成簡單鑒權功能
  4. 優化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 構建微服務統一認證解決方案(三)

github 倉庫


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM