領先一步
VMware 提供培訓和認證,助您快速提升。
瞭解更多我很高興地宣佈,Spring Security 6.3 將支援 OAuth 2.0 令牌交換授權型別 (RFC 8693),該支援已在最新的里程碑版本 (6.3.0-M3) 中提供預覽。此支援使能夠將令牌交換與 OAuth2 Client 一起使用。類似地,Spring Authorization Server 1.3 也隨之釋出了伺服器端支援,目前可在最新的里程碑版本 (1.3.0-M3) 中進行預覽。
Spring Security 的 OAuth2 Client 功能使我們能夠輕鬆地向使用 OAuth2 bearer 令牌保護的 API 發出受保護資源請求。類似地,Spring Security 的 OAuth2 Resource Server 功能使我們能夠使用 OAuth2 保護 API。接下來讓我們看看如何利用新支援來構建基於令牌交換的 OAuth2 流程。
假設我們有一個名為 user-service
的資源伺服器,提供訪問使用者資訊 API。為了向 user-service
發出請求,客戶端必須提供訪問令牌。假設令牌必須具有 user-service
的 audience (aud
claim)。這在 Spring Boot 配置屬性中可能如下所示
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: https://my-auth-server.com
audiences: user-service
現在假設我們想引入一個名為 message-service
的新資源伺服器,並從 user-service
中呼叫它。那麼假設這個新服務的令牌必須具有 message-service
的 audience。顯然,我們不能在對 message-service
的請求中重用對 user-service
請求中的令牌。但是,我們希望保留原始請求中使用者的身份。我們該如何實現這一點?
為了獲取 message-service
所需的訪問令牌,資源伺服器 user-service
必須成為一個客戶端,並用現有令牌交換一個保留原始令牌身份(使用者)的新令牌。這被稱為 “模擬 (impersonation)”,這正是 OAuth 2.0 令牌交換的設計場景。
要啟用令牌交換,我們需要將 user-service
配置為既是資源伺服器,又是可以使用令牌交換的客戶端,如下面的 Spring Boot 配置屬性所示
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: https://my-auth-server.com
audiences: user-service
client:
registration:
my-token-exchange-client:
provider: my-auth-server
client-id: token-client
client-secret: token
authorization-grant-type: urn:ietf:params:oauth:grant-type:token-exchange
client-authentication-method: client_secret_basic
scope:
- message.read
provider:
my-auth-server:
issuer-uri: https://my-auth-server.com
我們還需要在 Spring Security 中啟用新的授權型別,這可以透過釋出以下 bean 來實現
@Bean
public OAuth2AuthorizedClientProvider tokenExchange() {
return new TokenExchangeOAuth2AuthorizedClientProvider();
}
這就是開始使用令牌交換所需的全部內容。但是,如果我們想請求特定的 audience
或 resource
值,則需要在令牌請求中配置額外的引數,如下例所示
@Bean
public OAuth2AuthorizedClientProvider tokenExchange() {
var requestEntityConverter = new TokenExchangeGrantRequestEntityConverter();
requestEntityConverter.addParametersConverter((grantRequest) -> {
var parameters = new LinkedMultiValueMap<String, String>();
parameters.add(OAuth2ParameterNames.AUDIENCE, "message-service");
parameters.add(OAuth2ParameterNames.RESOURCE, "https://example.com/messages");
return parameters;
});
var accessTokenResponseClient = new DefaultTokenExchangeTokenResponseClient();
accessTokenResponseClient.setRequestEntityConverter(requestEntityConverter);
var authorizedClientProvider = new TokenExchangeOAuth2AuthorizedClientProvider();
authorizedClientProvider.setAccessTokenResponseClient(accessTokenResponseClient);
return authorizedClientProvider;
}
完成此配置後,我們可以在一個資源伺服器中獲取訪問令牌,並在向另一個資源伺服器傳送受保護資源請求時將其用作 Bearer
令牌。預設情況下,傳遞給資源伺服器的 Authorization
頭中的原始 bearer 令牌將用於獲取新的訪問令牌。
提示:有關如何使用此配置獲取訪問令牌併發出受保護資源請求的更多資訊,請參閱參考文件中的 授權客戶端功能。
為了完善整個流程,我們來構建一個全新的使用 Spring Authorization Server 的授權伺服器應用來支援此流程。
使用 Spring Initializr 並新增 OAuth2 Authorization Server 依賴,我們可以使用以下 Spring Boot 配置屬性配置一個功能齊全的授權伺服器
spring:
security:
user:
name: sally
password: password
oauth2:
authorizationserver:
client:
test-client:
registration:
client-id: test-client
client-secret: {noop}secret
client-authentication-methods:
- client_secret_basic
authorization-grant-types:
- authorization_code
- refresh_token
scopes:
- user.read
token-client:
registration:
client-id: token-client
client-secret: {noop}token
client-authentication-methods:
- client_secret_basic
authorization-grant-types:
- urn:ietf:params:oauth:grant-type:token-exchange
scopes:
- message.read
與客戶端類似,我們可能希望支援令牌交換的特定請求引數,例如 audience
或 resource
,這可以透過釋出以下 bean 來實現
@Bean
public OAuth2TokenCustomizer<JwtEncodingContext> accessTokenCustomizer() {
return (context) -> {
if (AuthorizationGrantType.TOKEN_EXCHANGE.equals(context.getAuthorizationGrantType())) {
OAuth2TokenExchangeAuthenticationToken tokenExchangeAuthentication = context.getAuthorizationGrant();
Set<String> resources = tokenExchangeAuthentication.getResources();
// TODO: Validate resource value(s) and map to the
// appropriate audience value(s) if needed...
context.getClaims().audience(...);
}
};
}
完成此配置後,授權伺服器將支援帶有 OAuth 2.0 令牌請求的可選 resource
引數的令牌交換授權型別,並能夠頒發允許資源伺服器作為客戶端模擬終端使用者的令牌。
在這篇部落格文章中,我們討論了令牌交換的“模擬”用例,並探討了資源伺服器(作為客戶端)和授權伺服器的簡單配置。
提示:有關其他示例,包括也受支援的名為“委託 (delegation)”的額外用例示例,請參閱 RFC 8693 的 附錄 A。
我希望您和我一樣對這項新支援感到興奮!我鼓勵您嘗試 Spring Authorization Server 中的 示例,其中包含這篇部落格文章的一個工作示例。也請在您自己的專案中嘗試 Spring Security 和 Spring Authorization Server 的里程碑版本。我們非常樂意收到您的反饋!