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

使用Spring OAuth2-Authorization-Server 1.2.2获取Token遇Access Denied问题

问题分析与修复方案

你的配置存在几个关键问题,导致返回Access Denied:

1. 客户端认证方法不匹配

你配置的客户端认证方法是CLIENT_SECRET_JWT,但你的请求是通过URL参数直接传递client_id和client_secret,这种方式对应的认证方法应该是CLIENT_SECRET_POST或者CLIENT_SECRET_BASIC。CLIENT_SECRET_JWT要求客户端生成JWT签名并携带认证,和你的请求方式完全不兼容。

2. 客户端密码未加密

Spring OAuth2 Authorization Server要求客户端密码必须加密存储,你直接明文设置clientSecret("secret")会导致认证失败,需要通过PasswordEncoder加密密码后再配置。

3. Client ID格式不匹配

配置中客户端ID是client-a(短横线分隔),但你的请求参数里是client_a(下划线分隔),两者不一致,服务端无法匹配到对应的客户端配置。

4. 冗余配置(建议修正)

client_credentials模式不需要授权同意和重定向URI,你配置的requireAuthorizationConsent(true)和redirectUri属于冗余设置,建议移除。


修改后的完整配置代码

@Configuration
@EnableWebSecurity
@Import(OAuth2AuthorizationServerConfiguration.class)
public class AuthorizationServerConfig {

    @Bean
    public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
        http
                .csrf(Customizer.withDefaults())
                .authorizeHttpRequests((authorize) -> authorize
                        .requestMatchers("/oauth2/**").permitAll()
                );

        return http.build();
    }

    @Bean
    public OAuth2AuthorizationService authorizationService() {
        return new InMemoryOAuth2AuthorizationService();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public RegisteredClientRepository registeredClientRepository(PasswordEncoder passwordEncoder) {
        RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString())
                .clientId("client_a") // 和请求参数保持一致,改为下划线格式
                .clientSecret(passwordEncoder.encode("secret")) // 对明文密码加密
                .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST) // 匹配请求传递方式
                .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
                .scope("read")
                // 移除冗余的redirectUri和授权同意配置
                .build();

        return new InMemoryRegisteredClientRepository(registeredClient);
    }

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

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

    @Bean
    public AuthorizationServerSettings authorizationServerSettings() {
        return AuthorizationServerSettings.builder().build();
    }
}

请求建议

修改配置后,建议将client_id和client_secret放在POST请求体中(表单参数),更符合CLIENT_SECRET_POST的规范:

curl -X POST http://localhost:9000/oauth2/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "scope=read" \
  -d "client_id=client_a" \
  -d "client_secret=secret"

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 16:13:19