在 Spring MVC 中初始化 OAuth WebClient Bean
Initialising OAuth WebClient Bean in Spring MVC
我在 Weblogic 12 上部署了一个 WebApp JSP 项目作为 WAR。
我的 gradle 构建包括 mvc 和 webflux:
implementation 'org.springframework.boot:spring-boot-starter-web:2.3.2.RELEASE'
implementation ("org.springframework.boot:spring-boot-starter-security:2.3.2.RELEASE")
implementation ("org.springframework.boot:spring-boot-starter-oauth2-client:2.3.2.RELEASE")
implementation ("org.springframework.boot:spring-boot-starter-webflux:2.3.2.RELEASE")
我正在尝试将 OAuth2 配置为使用来自我的客户端 JSP 应用程序的 client_credentials 流。
我需要 @Controller class 来使用 WebClient 并将访问令牌传播到资源服务器。
我创建 WebClient 的 Bean 如下所示。
@Bean
public ReactiveClientRegistrationRepository getRegistration() {
ClientRegistration registration = ClientRegistration
.withRegistrationId("ei-gateway")
.tokenUri("https://xxxxx.xxxxxxx.net/auth/oauth/v2/token")
.clientId("xxx-xxxx-43e9-a407-xxxxx")
.clientSecret("xxxxxx-3d21-4905-b6e5-xxxxxxxxxx")
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
.build();
return new InMemoryReactiveClientRegistrationRepository(registration);
}
@Bean
public WebClient webClient(ReactiveClientRegistrationRepository clientRegistrations, ServerOAuth2AuthorizedClientRepository authorizedClients) {
ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrations, authorizedClients);
oauth.setDefaultOAuth2AuthorizedClient(true);
return WebClient.builder()
.filter(oauth)
.defaultHeader("accept", "application/json")
.defaultHeader("content-type", "application/json")
.defaultHeader("environment", environment)
.filter(logRequest())
.filter(logResponse())
.build();
}
但是我在编译过程中遇到以下错误:
Could not autowire. There is more than one bean of 'ReactiveClientRegistrationRepository' type.
Beans:
clientRegistrationRepository (ReactiveOAuth2ClientConfigurations.class)
getRegistration (WebSecurityConfiguration.java)
然而,当我取消注释 getRegistration Bean 方法并通过 web.xml 配置 oauth 客户端注册时,然后在部署应用程序时出现此错误:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}:org.springframework.beans.factory.NoSuchBeanDefinitionException:No qualifying bean of type 'org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
我从 ReactiveOAuth2ClientAutoConfiguration 源代码中看到,当设置 ReactiveOAuth2ClientAutoConfiguration.NonServletApplicationCondition 时,Reactive OAuth2 自动配置不是 运行。
@Configuration(proxyBeanMethods = false)
@AutoConfigureBefore(ReactiveSecurityAutoConfiguration.class)
@EnableConfigurationProperties(OAuth2ClientProperties.class)
@Conditional(ReactiveOAuth2ClientAutoConfiguration.NonServletApplicationCondition.class)
@ConditionalOnClass({ Flux.class, EnableWebFluxSecurity.class, ClientRegistration.class })
@Import({ ReactiveOAuth2ClientConfigurations.ReactiveClientRegistrationRepositoryConfiguration.class,
ReactiveOAuth2ClientConfigurations.ReactiveOAuth2ClientConfiguration.class })
public class ReactiveOAuth2ClientAutoConfiguration {
}
任何人都可以建议一个行动方案吗?是否可以手动配置 ReactiveOAuth2ClientConfiguration?
谢谢
根据我的理解 ReactiveClientRegistrationRepository
不可用,因为您没有使用反应式堆栈,下面是如何设置 WebClient 以便在 Servlet 环境中使用。
设置应用程序属性,以便 Spring 为您自动装配 ClientRegistrationRepository
和 OAuth2AuthorizedClientRepository
。
spring.security.oauth2.client.provider.my-oauth-provider.token-uri=https://xxxxx.xxxxxxx.net/auth/oauth/v2/token
spring.security.oauth2.client.registration.ei-gateway.client-id=xxx-xxxx-43e9-a407-xxxxx
spring.security.oauth2.client.registration.ei-gateway.client-xxxxxx-3d21-4905-b6e5-xxxxxxxxxx
spring.security.oauth2.client.registration.ei-gateway.provider=my-oauth-provider
spring.security.oauth2.client.registration.ei-gateway.scope=read,write
spring.security.oauth2.client.registration.ei-gateway.authorization-grant-type=client_credentials
设置配置以指示您的应用程序需要充当 oauth2 客户端
@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.oauth2Client();
}
}
公开配置为使用客户端凭据的 WebClient bean
@Bean
public OAuth2AuthorizedClientManager authorizedClientManager(
ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientRepository authorizedClientRepository) {
OAuth2AuthorizedClientProvider authorizedClientProvider =
OAuth2AuthorizedClientProviderBuilder.builder()
.clientCredentials()
.build();
DefaultOAuth2AuthorizedClientManager authorizedClientManager =
new DefaultOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
return authorizedClientManager;
}
@Bean
WebClient webClient(OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager) {
ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Client =
new ServletOAuth2AuthorizedClientExchangeFilterFunction(
oAuth2AuthorizedClientManager);
// default registrationId - Only if you are not using the webClient to talk to different external APIs
oauth2Client.setDefaultClientRegistrationId("ei-gateway");
return WebClient.builder()
.apply(oauth2Client.oauth2Configuration())
.build();
}
现在您可以在代码中使用 WebClient 来访问外部受保护的资源。
参考文献:
https://docs.spring.io/spring-security/site/docs/current/reference/html5/#oauth2client
https://docs.spring.io/spring-security/site/docs/current/reference/html5/#oauth2Client-webclient-servlet
https://docs.spring.io/spring-security/site/docs/current/reference/html5/#defaulting-the-authorized-client
当应用程序未配置为资源服务器时,此设置对我有用,当应用程序需要使用 WebClient 时我不得不使用不同的配置,但也配置为资源服务器。
我在 Weblogic 12 上部署了一个 WebApp JSP 项目作为 WAR。
我的 gradle 构建包括 mvc 和 webflux:
implementation 'org.springframework.boot:spring-boot-starter-web:2.3.2.RELEASE'
implementation ("org.springframework.boot:spring-boot-starter-security:2.3.2.RELEASE")
implementation ("org.springframework.boot:spring-boot-starter-oauth2-client:2.3.2.RELEASE")
implementation ("org.springframework.boot:spring-boot-starter-webflux:2.3.2.RELEASE")
我正在尝试将 OAuth2 配置为使用来自我的客户端 JSP 应用程序的 client_credentials 流。
我需要 @Controller class 来使用 WebClient 并将访问令牌传播到资源服务器。
我创建 WebClient 的 Bean 如下所示。
@Bean
public ReactiveClientRegistrationRepository getRegistration() {
ClientRegistration registration = ClientRegistration
.withRegistrationId("ei-gateway")
.tokenUri("https://xxxxx.xxxxxxx.net/auth/oauth/v2/token")
.clientId("xxx-xxxx-43e9-a407-xxxxx")
.clientSecret("xxxxxx-3d21-4905-b6e5-xxxxxxxxxx")
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
.build();
return new InMemoryReactiveClientRegistrationRepository(registration);
}
@Bean
public WebClient webClient(ReactiveClientRegistrationRepository clientRegistrations, ServerOAuth2AuthorizedClientRepository authorizedClients) {
ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrations, authorizedClients);
oauth.setDefaultOAuth2AuthorizedClient(true);
return WebClient.builder()
.filter(oauth)
.defaultHeader("accept", "application/json")
.defaultHeader("content-type", "application/json")
.defaultHeader("environment", environment)
.filter(logRequest())
.filter(logResponse())
.build();
}
但是我在编译过程中遇到以下错误:
Could not autowire. There is more than one bean of 'ReactiveClientRegistrationRepository' type.
Beans:
clientRegistrationRepository (ReactiveOAuth2ClientConfigurations.class)
getRegistration (WebSecurityConfiguration.java)
然而,当我取消注释 getRegistration Bean 方法并通过 web.xml 配置 oauth 客户端注册时,然后在部署应用程序时出现此错误:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}:org.springframework.beans.factory.NoSuchBeanDefinitionException:No qualifying bean of type 'org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
我从 ReactiveOAuth2ClientAutoConfiguration 源代码中看到,当设置 ReactiveOAuth2ClientAutoConfiguration.NonServletApplicationCondition 时,Reactive OAuth2 自动配置不是 运行。
@Configuration(proxyBeanMethods = false)
@AutoConfigureBefore(ReactiveSecurityAutoConfiguration.class)
@EnableConfigurationProperties(OAuth2ClientProperties.class)
@Conditional(ReactiveOAuth2ClientAutoConfiguration.NonServletApplicationCondition.class)
@ConditionalOnClass({ Flux.class, EnableWebFluxSecurity.class, ClientRegistration.class })
@Import({ ReactiveOAuth2ClientConfigurations.ReactiveClientRegistrationRepositoryConfiguration.class,
ReactiveOAuth2ClientConfigurations.ReactiveOAuth2ClientConfiguration.class })
public class ReactiveOAuth2ClientAutoConfiguration {
}
任何人都可以建议一个行动方案吗?是否可以手动配置 ReactiveOAuth2ClientConfiguration?
谢谢
根据我的理解 ReactiveClientRegistrationRepository
不可用,因为您没有使用反应式堆栈,下面是如何设置 WebClient 以便在 Servlet 环境中使用。
设置应用程序属性,以便 Spring 为您自动装配 ClientRegistrationRepository
和 OAuth2AuthorizedClientRepository
。
spring.security.oauth2.client.provider.my-oauth-provider.token-uri=https://xxxxx.xxxxxxx.net/auth/oauth/v2/token
spring.security.oauth2.client.registration.ei-gateway.client-id=xxx-xxxx-43e9-a407-xxxxx
spring.security.oauth2.client.registration.ei-gateway.client-xxxxxx-3d21-4905-b6e5-xxxxxxxxxx
spring.security.oauth2.client.registration.ei-gateway.provider=my-oauth-provider
spring.security.oauth2.client.registration.ei-gateway.scope=read,write
spring.security.oauth2.client.registration.ei-gateway.authorization-grant-type=client_credentials
设置配置以指示您的应用程序需要充当 oauth2 客户端
@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.oauth2Client();
}
}
公开配置为使用客户端凭据的 WebClient bean
@Bean
public OAuth2AuthorizedClientManager authorizedClientManager(
ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientRepository authorizedClientRepository) {
OAuth2AuthorizedClientProvider authorizedClientProvider =
OAuth2AuthorizedClientProviderBuilder.builder()
.clientCredentials()
.build();
DefaultOAuth2AuthorizedClientManager authorizedClientManager =
new DefaultOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
return authorizedClientManager;
}
@Bean
WebClient webClient(OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager) {
ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Client =
new ServletOAuth2AuthorizedClientExchangeFilterFunction(
oAuth2AuthorizedClientManager);
// default registrationId - Only if you are not using the webClient to talk to different external APIs
oauth2Client.setDefaultClientRegistrationId("ei-gateway");
return WebClient.builder()
.apply(oauth2Client.oauth2Configuration())
.build();
}
现在您可以在代码中使用 WebClient 来访问外部受保护的资源。
参考文献:
https://docs.spring.io/spring-security/site/docs/current/reference/html5/#oauth2client https://docs.spring.io/spring-security/site/docs/current/reference/html5/#oauth2Client-webclient-servlet https://docs.spring.io/spring-security/site/docs/current/reference/html5/#defaulting-the-authorized-client
当应用程序未配置为资源服务器时,此设置对我有用,当应用程序需要使用 WebClient 时我不得不使用不同的配置,但也配置为资源服务器。