依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
配置
spring:
security:
oauth2:
client:
registration:
my-client:
provider: my-auth
client-id: client-id
client-secret: client-secret
authorization-grant-type: client_credentials
scope: all
provider:
my-auth:
token-uri: http://localhost/oauth/token
@Configuration
public class ClientConfig {
@Bean
public OAuth2AuthorizedClientManager authorizedClientManager(ClientRegistrationRepository clientRegistration,
OAuth2AuthorizedClientService authorizedClientService) {
OAuth2AuthorizedClientProvider authorizedClientProvider =
OAuth2AuthorizedClientProviderBuilder.builder()
.clientCredentials()
.build();
AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager =
new AuthorizedClientServiceOAuth2AuthorizedClientManager(
clientRegistration, authorizedClientService);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
return authorizedClientManager;
}
}
```java
获取TOKEN
@Autowired
OAuth2AuthorizedClientManager authorizedClientManager;
public String getAccessToken() {
OAuth2AuthorizeRequest request = OAuth2AuthorizeRequest
.withClientRegistrationId("my-client")
.principal("my client")
.build();
return Optional.ofNullable(oAuth2AuthorizedClientManager)
.map(clientManager -> clientManager.authorize(request))
.map(OAuth2AuthorizedClient::getAccessToken)
.map(AbstractOAuth2Token::getTokenValue)
.orElseThrow(() -> new RuntimeException("令牌获取失败"));
}
源码
- 授权管理器
org.springframework.security.oauth2.client.AuthorizedClientServiceOAuth2AuthorizedClientManager
public OAuth2AuthorizedClient authorize(OAuth2AuthorizeRequest authorizeRequest) {
...
contextBuilder = OAuth2AuthorizationContext.withClientRegistration(clientRegistration);
...
OAuth2AuthorizationContext authorizationContext = buildAuthorizationContext(authorizeRequest, principal,
contextBuilder);
try {
authorizedClient = this.authorizedClientProvider.authorize(authorizationContext);
}
}
- 客户端凭据授权供应者
org.springframework.security.oauth2.client.ClientCredentialsOAuth2AuthorizedClientProvider
// 客户端凭据授权模式的访问令牌客户端
private OAuth2AccessTokenResponseClient<OAuth2ClientCredentialsGrantRequest> accessTokenResponseClient = new DefaultClientCredentialsTokenResponseClient();
// 客户端授权
public OAuth2AuthorizedClient authorize(OAuth2AuthorizationContext context) {
Assert.notNull(context, "context cannot be null");
ClientRegistration clientRegistration = context.getClientRegistration();
if (!AuthorizationGrantType.CLIENT_CREDENTIALS.equals(clientRegistration.getAuthorizationGrantType())) {
return null;
}
OAuth2AuthorizedClient authorizedClient = context.getAuthorizedClient();
if (authorizedClient != null && !hasTokenExpired(authorizedClient.getAccessToken())) {
// 客户端已经授权并且没有过期,则无需重复授权
return null;
}
// 请求访问令牌
OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest = new OAuth2ClientCredentialsGrantRequest(
clientRegistration);
OAuth2AccessTokenResponse tokenResponse = getTokenResponse(clientRegistration, clientCredentialsGrantRequest);
return new OAuth2AuthorizedClient(clientRegistration, context.getPrincipal().getName(),
tokenResponse.getAccessToken());
}
// 请求访问令牌
private OAuth2AccessTokenResponse getTokenResponse(ClientRegistration clientRegistration,
OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest) {
try {
return this.accessTokenResponseClient.getTokenResponse(clientCredentialsGrantRequest);
}
catch (OAuth2AuthorizationException ex) {
throw new ClientAuthorizationException(ex.getError(), clientRegistration.getRegistrationId(), ex);
}
}
- 客户端凭据模式的令牌客户端
org.springframework.security.oauth2.client.endpoint.DefaultClientCredentialsTokenResponseClient
// 请求转换器
private Converter<OAuth2ClientCredentialsGrantRequest, RequestEntity<?>> requestEntityConverter = new OAuth2ClientCredentialsGrantRequestEntityConverter();
// 获取令牌
public OAuth2AccessTokenResponse getTokenResponse(
OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest) {
Assert.notNull(clientCredentialsGrantRequest, "clientCredentialsGrantRequest cannot be null");
RequestEntity<?> request = this.requestEntityConverter.convert(clientCredentialsGrantRequest);
ResponseEntity<OAuth2AccessTokenResponse> response = getResponse(request);
OAuth2AccessTokenResponse tokenResponse = response.getBody();
if (CollectionUtils.isEmpty(tokenResponse.getAccessToken().getScopes())) {
// 如果访问令牌不包含scopes,则取客户端注册信息中的scope
tokenResponse = OAuth2AccessTokenResponse.withResponse(tokenResponse)
.scopes(clientCredentialsGrantRequest.getClientRegistration().getScopes())
.build();
}
return tokenResponse;
}
- 客户端证书授权请求实体转换器
org.springframework.security.oauth2.client.endpoint.OAuth2ClientCredentialsGrantRequestEntityConverter
public RequestEntity<?> convert(T authorizationGrantRequest) {
// 将客户端ID和密码以BASIC认证模式装入HEADER
HttpHeaders headers = getHeadersConverter().convert(authorizationGrantRequest);
// scope和grant_type参数
MultiValueMap<String, String> parameters = getParametersConverter().convert(authorizationGrantRequest);
URI uri = UriComponentsBuilder
.fromUriString(authorizationGrantRequest.getClientRegistration().getProviderDetails().getTokenUri())
.build().toUri();
return new RequestEntity<>(parameters, headers, HttpMethod.POST, uri);
}