The bean 'oauth2ClientContext', defined in...(OAuth2ClientContext bean重复)

在Spring Cloud Greenwich集成OAuth2过程中,遇到重复定义oauth2ClientContext bean的问题。通过调整配置和注解,避免了bean冲突,实现了OAuth2的正确集成。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

以下是在Spring-Cloud(Greenwich.RELEASE)集成OAuth2(2.3.3.RELEASE)过程中出现的一个问题,项目管理工具使用的gradle,学习用例产生的问题仅供参考(如学习有误,请及时打脸纠正嘴型)。

gradle引入的Spring-Cloud-OAuth2依赖:

implementation 'org.springframework.cloud:spring-cloud-starter-oauth2'

Application的入口类:

package com.hoku.account;

import org.springframework.boot.SpringApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;
@EnableOAuth2Client
@EnableFeignClients
@SpringCloudApplication
public class AccountApplication {
    public static void main(String[] args) {
        SpringApplication.run(AccountApplication.class);
    }
}

application.yml oauth2部分配置信息:

security:
  oauth2:
    # XXXXXResourceDetails
    client:
      clientId: ${ACCOUNT_CLIENT_ID:client1}
      clientSecret: ${ACCOUNT_CLIENT_PASSWORD:123456}
      accessTokenUri: ${ACCESS_TOKEN_URI:http://localhost:9200/uaa/oauth/token}
      grant-type: client_credentials
      scope: server
    #ResourceServerProperties
    resource:
      userInfoUri: ${USER_INFO_URI:http://localhost:9200/uaa/user/info}

在搭建好注册中心(Eureka),认证授权服务(OAuth2)之后,搭建基于认证授权服务的客户端时,启动出现如下错误:

The bean 'oauth2ClientContext', defined in class path resource [org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2RestOperationsConfiguration$SingletonScopedConfiguration.class], could not be registered. A bean with that name has already been defined in BeanDefinition defined in class path resource [org/springframework/security/oauth2/config/annotation/web/configuration/OAuth2ClientConfiguration$OAuth2ClientContextConfiguration.class] and overriding is disabled.

Action:

Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true

 错误信息提示bean名称为:oauth2ClientContext)已经在OAuth2ClientConfiguration中定义了,在OAuth2RestOperationsConfiguration$SingletonScopedConfiguration中无法再次定义,并且提示可以通过在application.yml中添加配置属性spring.main.allow-bean-definition-overridng=true解决这个问题,该属性是可以让后面定义的bean覆盖已经存在的同类型bean. 该方法可以解决问题启动报错问题,但是bean覆盖并不是合理的方式。

下面说一下另外一种方式:

首先根据报错提到的两个Configuration,OAuth2RestOperationsConfiguration$SingletonScopedConfiguration和OAuth2ClientConfiguration$OAuth2ClientContextConfiguration,一个来自与spring-security-oauth2-autoconfigure,另一个来自于spring-security-oauth2。

在EnableOAuth2Client注解中可以看到,OAuth2ClientConfiguration是定义导入的配置,所以OAuth2RestOperationsConfiguration应该是由于autoconfigure原因初始化的配置,所以想办法排除掉OAuth2RestOperationsConfiguration$SingletonScopedConfiguration配置应该是可以解决问题的。

@EnableOAuth2Client源码:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(OAuth2ClientConfiguration.class)
public @interface EnableOAuth2Client {

}

OAuth2ClientConfiguration源码:

@Configuration
public class OAuth2ClientConfiguration {

	@Bean
	public OAuth2ClientContextFilter oauth2ClientContextFilter() {
		OAuth2ClientContextFilter filter = new OAuth2ClientContextFilter();
		return filter;
	}

	@Bean
	@Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES)
	protected AccessTokenRequest accessTokenRequest(@Value("#{request.parameterMap}")
	Map<String, String[]> parameters, @Value("#{request.getAttribute('currentUri')}")
	String currentUri) {
		DefaultAccessTokenRequest request = new DefaultAccessTokenRequest(parameters);
		request.setCurrentUri(currentUri);
		return request;
	}
	
	@Configuration
	protected static class OAuth2ClientContextConfiguration {
		
		@Resource
		@Qualifier("accessTokenRequest")
		private AccessTokenRequest accessTokenRequest;
		//定义了一个session级的bean名字默认为oauth2ClientContext
		@Bean
		@Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)
		public OAuth2ClientContext oauth2ClientContext() {
			return new DefaultOAuth2ClientContext(accessTokenRequest);
		}
		
	}

}

OAuth2RestOperationsConfiguration$SingletonScopedConfiguration部分源码:

@Configuration
@ConditionalOnClass(EnableOAuth2Client.class)
public class OAuth2RestOperationsConfiguration {

	@Configuration
	@Conditional(ClientCredentialsCondition.class) //让这个条件不成立即可
	protected static class SingletonScopedConfiguration {

		@Bean
		@ConfigurationProperties(prefix = "security.oauth2.client")
		@Primary
		public ClientCredentialsResourceDetails oauth2RemoteResource() {
			ClientCredentialsResourceDetails details = new ClientCredentialsResourceDetails();
			return details;
		}
                //此处oauth2ClientContext bean在OAuth2ClientConfiguration中已经定义
		@Bean
		public DefaultOAuth2ClientContext oauth2ClientContext() {
			return new DefaultOAuth2ClientContext(new DefaultAccessTokenRequest());
		}

	}
        ....
        /**
	 * Condition to check for client credentials.
	 */
	static class ClientCredentialsCondition extends AnyNestedCondition {

		ClientCredentialsCondition() {
			super(ConfigurationPhase.PARSE_CONFIGURATION);
		}
                //application.yml中配置了这个grant-type属性,所以导致该条件是matched,
                //所以让该条件不成立就不会启用SingletonScopedConfiguration 配置,就不会
                //出现多个oauth2ClientContext的bean
		@ConditionalOnProperty(prefix = "security.oauth2.client", name = "grant-type", havingValue = "client_credentials", matchIfMissing = false)
		static class ClientCredentialsConfigured {
		}
                //spring-boot是个web程序所以这个条件不会matched
		@ConditionalOnNotWebApplication
		static class NoWebApplication {
		}

	}

}

 下面才是具体解决方法:

1. 去掉application.yml 中的grant-type属性,其他不变。

2. 好了

再次启动,不会出现oauth2ClientContext重复定义问题了。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值