当前位置: 首页 > 知识库问答 >
问题:

在Spring MVC中初始化OAuth WebClient Bean

寿高阳
2023-03-14

我在Weblogic 12上部署了一个WebApp JSP项目作为WAR。

我的gradle构建包括mvc和webflow:

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类来使用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) 

然而,当我取消注释get注册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源代码中看到,Reactive OAuth2自动配置在ReactiveOAuth2ClientAutoConfiguration时未运行。设置了NonServletApplication ation条件。

@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 {
}

有人能提出行动方案吗?是否可以手动配置ReactiveOAuth2Client配置?

谢啦

共有1个答案

凌嘉志
2023-03-14

据我所知,ReactiveClientRegistrationRepository不可用,因为您没有使用Reactor栈,下面介绍如何设置WebClient以在Servlet环境中使用。

设置应用程序属性,以便Spring自动为您提供客户注册库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-网络客户端servlethttps://docs.spring.io/spring-security/site/docs/current/reference/html5/#defaulting-授权客户

当应用程序未配置为资源服务器时,此设置对我有效,当应用程序需要使用WebClient时,我必须使用不同的配置,但也配置为资源服务器。

 类似资料:
  • 据我所知,在Java11中,这两个操作可以在一行中完成,不是吗?

  • Initialization 初始化 Although it doesn’t look superficially very different from initialization in C or C++, initialization in Go is more powerful. Complex structures can be built during initialization a

  • 初始化是为类、结构体或者枚举准备实例的过程。这个过需要给实例里的每一个存储属性设置一个初始值并且在新实例可以使用之前执行任何其他所必须的配置或初始化。 你通过定义初始化器来实现这个初始化过程,它更像是一个用来创建特定类型新实例的特殊的方法。不同于 Objective-C 的初始化器,Swift 初始化器不返回值。这些初始化器主要的角色就是确保在第一次使用之前某类型的新实例能够正确初始化。 类类型的

  • new iSlider(DOM, DATA, OPTIONS) Name Type Description DOM dom 容器dom节点 DATA Array 数据列表 OPTIONS Object 配置项 DOM new iSlider(DOM, DATA, OPTIONS); {HTMLElement} 容器dom节点 作为第一个参数并不是必须的,会被OPTIONS.dom覆盖,但是这十分必

  • 确认初始化操作 1)初始化操作用来清空此统计ID的统计数据 2)与启用新的统计ID不同的是,初始化操作使您不需更换网站上的统计代码就可以重新开始统计 注意:初始化操作将清除此统计ID的所有统计数据,此操作不可恢复!!!

  • 创建版本库 git 基于文件夹(工作树)进行版本控制,在一个文件夹中创建 git版本库: $ cd project/ $ git init Initialized empty Git repository in .git/ 输出信息:在当前文件夹的 .git/ 目录下创建版本库 将文件提交到 git索引: git add file1 file2 file3 …… 更方便的作法是

  • 1. 引入sdk 下载wechat-mudu.min.js到小程序项目,建议放utils目录下 const Mudu = require('./utils/wechat-mudu.min') 2. 设置小程序code获取session_key地址 本方法已废弃 sdk会在初始化的时候获取用户的微信资料并设置到目睹平台,所以需要设置该地址用户获取用户openid, 详见用户 Mudu.setOp

  • 1. 引入sdk文件 // 播放器依赖于Promise,兼容ie及其它低版本浏览器的用户需添加polyfill, 如下: <script src="//static.mudu.tv/es6-promise/es6-promise.auto.min.js"></script> // 以下为必须添加项 <script>window.FETCHER_SERVER_URL = "ws://fetcher