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

OAuth2客户端报错:无法解析指定Issuer的配置求助

排查OAuth2客户端报错:Unable to resolve Configuration with the provided Issuer of "http://localhost:9000"

为学习OAuth2机制,我搭建了包含三个服务模块的示例应用:

  • OAuth2授权服务器
  • 资源服务器
  • OAuth2客户端

前两个服务运行正常,但在配置OAuth2客户端时,持续收到错误:Unable to resolve Configuration with the provided Issuer of "http://localhost:9000",排查数小时仍未解决,以下是三个服务的完整配置信息,求排查方向。

资源服务器配置

application.yml

server:
  port: 8080

spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          issuer-uri: "http://localhost:9000"
          jwk-set-uri: "http://localhost:9000/oauth2/jwks"

SecurityConfig.java

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    MvcRequestMatcher.Builder mvc(HandlerMappingIntrospector introspector) {
        return new MvcRequestMatcher.Builder(introspector);
    }

    @Bean
    @Order(1)
    public SecurityFilterChain filterChain(HttpSecurity http, MvcRequestMatcher.Builder mvc) throws Exception {
        http
                // SECURITY
                .csrf(CsrfConfigurer::disable)
                .headers(headers -> headers
                        .frameOptions(HeadersConfigurer.FrameOptionsConfig::disable))
                // RISK
                .authorizeHttpRequests((auth) -> auth
                        .requestMatchers(mvc.pattern("/data-api/users")).denyAll()
                        .requestMatchers(mvc.pattern("/data-api/users/**")).denyAll()
                        .requestMatchers(mvc.pattern("/data-api/taco-orders")).denyAll()
                        .requestMatchers(mvc.pattern("/data-api/taco-orders/**")).denyAll()
                        .requestMatchers(mvc.pattern(HttpMethod.POST, "/data-api/tacos")).authenticated()
                        .requestMatchers(mvc.pattern(HttpMethod.DELETE, "/data-api/tacos/**")).denyAll()
                        .requestMatchers(mvc.pattern(HttpMethod.POST, "/data-api/ingredients")).hasAuthority("SCOPE_ingredients.write")
                        .requestMatchers(mvc.pattern(HttpMethod.DELETE, "/data-api/ingredients/**")).hasAuthority("SCOPE_ingredients.delete")
                        .requestMatchers(mvc.pattern("/design"), mvc.pattern("/orders")).hasRole("USER")
                        .requestMatchers(mvc.pattern("/"), mvc.pattern("/**")).permitAll()
                        .requestMatchers(toH2Console()).permitAll()
                        .anyRequest().authenticated())
                .oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()))
                .formLogin((formLogin) -> formLogin
                        .loginPage("/login")
                        .defaultSuccessUrl("/design"));
        return http.build();
    }
}

授权服务器配置

application.yml

server:
  port: 9000

AuthServerConfig.java

@Configuration(proxyBeanMethods = false)
public class AuthServerConfig {

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SecurityFilterChain authServerSecurityFilterChain(HttpSecurity http) throws Exception {
        OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
        http
                .formLogin(Customizer.withDefaults());
        return http.build();
    }

    @Bean
    public RegisteredClientRepository registeredClientRepository(PasswordEncoder passwordEncoder) {
        RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString())
                .clientId("taco-cloud-client")
                .clientSecret(passwordEncoder.encode("secret"))
                .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
                .authorizationGrantTypes(grantTypes -> grantTypes.addAll(Set.of(
                        AuthorizationGrantType.AUTHORIZATION_CODE,
                        AuthorizationGrantType.REFRESH_TOKEN
                )))
                .redirectUris(redirectUris -> redirectUris.addAll(Set.of(
                        "http://127.0.0.1:9090/authorized",
                        "http://127.0.0.1:9090/login/oauth2/code/taco-cloud-client"
                )))
                .scopes(scopes -> scopes.addAll(Set.of(
                        "ingredients.write",
                        "ingredients.delete",
                        OidcScopes.OPENID
                )))
                .clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
                .build();
        return new InMemoryRegisteredClientRepository(registeredClient);
    }

    @Bean
    public JWKSource<SecurityContext> jwkSource()
            throws NoSuchAlgorithmException {
        RSAKey rsaKey = generateRsa();
        JWKSet jwkSet = new JWKSet(rsaKey);
        return (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
    }

    @Bean
    public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
        return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
    }

    private static RSAKey generateRsa() throws NoSuchAlgorithmException {
        KeyPair keyPair = generateRsaKey();
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        return new RSAKey.Builder(publicKey)
                .privateKey(privateKey)
                .keyID(UUID.randomUUID().toString())
                .build();
    }

    private static KeyPair generateRsaKey() throws NoSuchAlgorithmException {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(2048);
        return keyPairGenerator.generateKeyPair();
    }
}

SecurityConfig.java

@EnableWebSecurity
@Configuration
public class SecurityConfig {

    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .authorizeHttpRequests(auth -> auth
                        .anyRequest().authenticated())
                .formLogin(Customizer.withDefaults());
        return http.build();
    }
}

OAuth2客户端配置(报错服务)

application.yml

server:
  port: 9090

spring:
  security:
    oauth2:
      client:
        registration:
          taco-cloud-client:
            provider: tacocloud
            client-id: taco-cloud-client
            client-secret: secret
            authorization-grant-type: authorization_code
            redirect-uri: "http://127.0.0.1:9090/login/oauth2/code/{registrationId}"
            scope:
              - openid
              - ingredients.read
              - ingredients.write
        provider:
          tacocloud:
            issuer-uri: http://localhost:9000

SecurityConfig.java

@EnableWebSecurity
@Configuration(proxyBeanMethods = false)
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .authorizeHttpRequests(authorize ->
                        authorize
                                .anyRequest().authenticated())
                .oauth2Login(oauth2Login ->
                        oauth2Login.loginPage("/oauth2/authorization/taco-cloud-client"))
                .oauth2Client(Customizer.withDefaults());
        return http.build();
    }
}

希望能得到排查问题的方向,感谢!


内容的提问来源于stack exchange,提问作者IceMajor

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 05:55:02