gpt4 book ai didi

spring-boot - 如何使用 client_credentials 从资源服务器访问另一个 oauth2 资源?

转载 作者:行者123 更新时间:2023-12-04 01:38:20 24 4
gpt4 key购买 nike

我想使用 client_credentials 从 react 性资源服务器访问另一个受 oauth2 保护的资源。我使用颁发的 token 访问资源服务器的部分正在运行,但没有使用 webclient 调用其他资源。

使用 UnAuthenticatedServerOAuth2AuthorizedClientRepository 我得到 serverWebExchange must be null,使用 AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository 我得到 principalName must be null

使用 https://www.baeldung.com/spring-webclient-oauth2只要我将客户端称为 CommandLineRunner,它就可以工作。我在 stackoverflow 上找到的其他建议都没有用。

我在这里错过了什么?我正在使用 Spring Security 5.2.0 和 Spring Boot 2.2.0。

客户端配置:

@Configuration
public class ClientSecurityConfig {

// UnAuthenticatedServerOAuth2AuthorizedClientRepository version

@Bean
WebClient webClient(ReactiveClientRegistrationRepository clientRegistrations) {
ServerOAuth2AuthorizedClientExchangeFilterFunction oauth =
new ServerOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrations, new UnAuthenticatedServerOAuth2AuthorizedClientRepository());

return WebClient.builder()
.filter(oauth)
.build();
}

@Bean
ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider(CustomClientConfig clientConfig) {
return ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
.clientCredentials(clientCredentialsGrantBuilder ->
clientCredentialsGrantBuilder.accessTokenResponseClient(new CustomClient(clientConfig))) // Used to send extra parameters to adfs server
.build();
}


// AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository version

@Bean
WebClient webClient(ReactiveOAuth2AuthorizedClientManager authorizedClientManager) {
ServerOAuth2AuthorizedClientExchangeFilterFunction oauth =
new ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
return WebClient.builder()
.filter(oauth)
.build();
}
}

@Bean
ReactiveOAuth2AuthorizedClientManager authorizedClientManager(
ReactiveClientRegistrationRepository clientRegistrationRepository,
ServerOAuth2AuthorizedClientRepository authorizedClientRepository, CustomClientConfig clientConfig) {

ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider =
ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
.clientCredentials(clientCredentialsGrantBuilder ->
clientCredentialsGrantBuilder.accessTokenResponseClient(new CustomClient(clientConfig))) // Used to send extra parameters to adfs server
.build();
DefaultReactiveOAuth2AuthorizedClientManager authorizedClientManager =
new DefaultReactiveOAuth2AuthorizedClientManager(clientRegistrationRepository, authorizedClientRepository);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);

return authorizedClientManager;
}
}

资源服务器配置:

@EnableWebFluxSecurity
class ResourceServerConfig {
@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http
.authorizeExchange(exchanges ->
exchanges
.pathMatchers("/actuators/**", "/api/v1").permitAll()
.pathMatchers("/api/v1/**").hasAuthority("SCOPE_read")
.anyExchange().authenticated()
)
.formLogin().disable()
.httpBasic().disable()
.oauth2Client(withDefaults())
.oauth2ResourceServer().jwt();
return http.build();
}
@RestController()
@RequestMapping("/api/v1")
static class Ctrl {
final static Logger logger = LoggerFactory.getLogger(Ctrl.class);
final WebClient webClient;

public Ctrl(WebClient webClient) {
this.webClient = webClient;
}

@RequestMapping("protected")
Mono<JsonNode> protected(@RequestParam String data) {
return webClient.post()
.uri("https://other-oauth2-protected-resource")
.attributes(clientRegistrationId("myclient"))
.bodyValue("{\"data\": \"" + data + "\"}")
.retrieve()
.bodyToMono(JsonNode.class);
}
}
}

应用程序.yml:

spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: http://adfsserver.com/adfs/services/trust
jwk-set-uri: https://adfsserver.com/adfs/discovery/keys
client:
registration:
myclient:
provider: adfs
client-id: <client-id>
client-secret: <client-secret>
authorization-grant-type: client_credentials
scope: read
provider:
adfs:
token-uri: https://adfsserver.com/adfs/oauth2/token
jwk-set-uri: https://adfsserver.com/adfs/discovery/keys

最佳答案

这最近已由 Spring 项目贡献者修复,作为此 PR 的一部分但不幸的是,官方 Spring 文档尚未更新。

正常的 servlet 方法文档是 here如果您更喜欢选择“响应式(Reactive)”方法,那么配置 webclient 只需要两个 bean:

  1. AuthorizedClientManager Bean,以及
  2. webClient Bean
  @Bean
public ReactiveOAuth2AuthorizedClientManager authorizedClientManager(
ReactiveClientRegistrationRepository clientRegistrationRepository,
ReactiveOAuth2AuthorizedClientService authorizedClientService) {

ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider =
ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
.clientCredentials()
.build();

AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager authorizedClientManager =
new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientService);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);

return authorizedClientManager;
}


@Bean
public WebClient webClient(ReactiveOAuth2AuthorizedClientManager authorizedClientManager) {
ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
return WebClient.builder().filter(oauth).build();
}

可以引用我的Github Gist它具有所有必需的配置。

关于spring-boot - 如何使用 client_credentials 从资源服务器访问另一个 oauth2 资源?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58595062/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com