You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring OAuth2应用报错:找不到OAuth2AuthorizedClientService的唯一构造方法

Spring OAuth2 获取AccessToken时构造器异常问题

问题详情

在简单Spring OAuth2应用中尝试获取access token,使用OAuth2AuthorizedClientService调用/test端点时触发以下错误:

java.lang.IllegalStateException: No primary or single unique constructor found for interface org.springframework.security.oauth2.client.OAuth2AuthorizedClientService

at org.springframework.beans.BeanUtils.getResolvableConstructor(BeanUtils.java:267) ~[spring-beans-5.3.21.jar:5.3.21]
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.createAttribute(ModelAttributeMethodProcessor.java:219) ~[spring-web-5.3.21.jar:5.3.21]
at org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor.createAttribute(ServletModelAttributeMethodProcessor.java:85) ~[spring-webmvc-5.3.22.jar:5.3.22]
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:147) ~[spring-web-5.3.21.jar:5.3.21]
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:122) ~[spring-web-5.3.21.jar:5.3.21]
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:179) ~[spring-web-5.3.21.jar:5.3.21]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:146) ~[spring-web-5.3.21.jar:5.3.21]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) ~[spring-webmvc-5.3.22.jar:5.3.22]
...

项目结构包含主类、配置类、控制器,两个端点:/home(允许所有访问)、/test(需认证),错误在请求/test时触发。

配置类代码

@Configuration
public class SecurityConfig {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .mvcMatchers("/test/**").authenticated()
                .mvcMatchers("/home/**").permitAll()
            .and().oauth2Login();

        return http.build();
    }

    private ClientRegistration clientRegistration() {
        return CommonOAuth2Provider.GITHUB.getBuilder("github").clientId("<not sharing>")
                .clientSecret("<not sharing>")
                .scope("user:email").build();
    }

    @Bean 
    public ClientRegistrationRepository clientRepository() {
         ClientRegistration clientReg = clientRegistration();
         
         return new InMemoryClientRegistrationRepository(clientReg); 
    }
}

控制器代码

@RestController
public class TestController {
    @GetMapping("/home")
    public String home() {
        return "home page";
    }

    @GetMapping("/test")
    public OAuth2AuthenticationToken testToken(OAuth2AuthenticationToken token, 
            OAuth2AuthorizedClientService svc) {
        
        var t = svc.loadAuthorizedClient(token.getAuthorizedClientRegistrationId(), token.getName());
        System.out.println(t.getAccessToken().getTokenValue());
        
        return token;
    }
}

依赖配置

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-web</artifactId>
    <version>5.7.2</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
    <version>5.7.2</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-client</artifactId>
    <version>2.7.2</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.7.2</version>
</dependency>

使用JDK版本:jdk-16.0.1

解决方案

错误核心是控制器方法直接将OAuth2AuthorizedClientService作为参数传入,Spring MVC会把它当作@ModelAttribute尝试实例化,但它是接口,没有可实例化的构造器,因此抛出异常。

正确做法是通过依赖注入获取实例,而非作为方法参数:

修改后的控制器代码

@RestController
public class TestController {
    // 构造器注入OAuth2AuthorizedClientService(Spring推荐方式)
    private final OAuth2AuthorizedClientService authorizedClientService;

    public TestController(OAuth2AuthorizedClientService authorizedClientService) {
        this.authorizedClientService = authorizedClientService;
    }

    @GetMapping("/home")
    public String home() {
        return "home page";
    }

    @GetMapping("/test")
    public OAuth2AuthenticationToken testToken(OAuth2AuthenticationToken token) {
        var authorizedClient = authorizedClientService.loadAuthorizedClient(
                token.getAuthorizedClientRegistrationId(), 
                token.getName()
        );
        System.out.println(authorizedClient.getAccessToken().getTokenValue());
        
        return token;
    }
}

补充说明:spring-boot-starter-oauth2-client已自动配置OAuth2AuthorizedClientService的实现类(InMemoryOAuth2AuthorizedClientService),无需手动配置该Bean,直接注入即可使用。


内容的提问来源于stack exchange,提问作者Krusty the Clown

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 13:27:23