spring security5.x Oauth2 client_credentials模式客户端获取token源码

2021-12-07 16:09:51 浏览数 (2)

依赖

代码语言:javascript复制
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>

配置

代码语言:javascript复制
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            
代码语言:javascript复制
@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

代码语言:javascript复制
@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
代码语言:javascript复制
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
代码语言:javascript复制
// 客户端凭据授权模式的访问令牌客户端
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
代码语言:javascript复制
// 请求转换器
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
代码语言:javascript复制
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);
}

0 人点赞