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

Spring OAuth2如何修改/oauth2/introspect端点无需client_id和client_secret

问题描述

原本实现的是自定义Spring OAuth2授权服务器的/oauth2/introspect端点来校验令牌,示例请求为:http://localhost:8080/oauth2/introspect?token=tokenValueHere&client_id=client&client_secret=secret,但需求调整为仅校验令牌,无需传入client_id和client_secret。

已尝试自定义getAuthenticationProvider方法,但不携带client_id和client_secret请求时,直接返回401 Unauthorized,且自定义方法中的打印语句Going to this method未输出,说明该方法被前置拦截,根本没执行。

相关代码如下:

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
    http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
            .tokenIntrospectionEndpoint(a -> a.authenticationProvider(getAuthenticationProvider()));

    http.csrf().disable();

    return http.build();
}

private AuthenticationProvider getAuthenticationProvider() {
    System.out.println("Going to this method");
    return new AuthenticationProvider() {
        @Override
        public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        
            if (authentication.getPrincipal() == null || authentication.getCredentials() == null) {
                return authentication;
            }
            throw new BadCredentialsException("Invalid credentials");
        }
        @Override
        public boolean supports(Class<?> authentication) {
            return OAuth2TokenIntrospectionAuthenticationToken.class.isAssignableFrom(authentication);
        }
    };
}

依赖配置:

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-oauth2-authorization-server</artifactId>
    <version>1.0.2</version>
</dependency>
解决方案

出现401的核心原因是Spring Authorization Server默认要求/oauth2/introspect端点必须经过客户端认证,你的自定义AuthenticationProvider还没执行就被默认的客户端认证拦截了。要实现无客户端认证的令牌校验,需做以下调整:

1. 取消端点的客户端认证拦截

修改SecurityFilterChain配置,允许匿名访问/oauth2/introspect,同时覆盖默认的端点配置:

@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
    OAuth2AuthorizationServerConfigurer authorizationServerConfigurer = new OAuth2AuthorizationServerConfigurer();
    http.apply(authorizationServerConfigurer);

    // 配置令牌 introspect 端点的自定义逻辑
    authorizationServerConfigurer.tokenIntrospectionEndpoint(endpoint ->
            endpoint.authenticationProvider(getIntrospectionAuthenticationProvider())
    );

    // 允许匿名访问introspect端点,绕过客户端认证
    http.authorizeHttpRequests(auth -> auth
            .requestMatchers("/oauth2/introspect").permitAll()
            .anyRequest().authenticated()
    );

    http.csrf().disable();
    return http.build();
}

2. 实现真实令牌校验逻辑

原来的AuthenticationProvider逻辑未实际校验令牌有效性,需结合OAuth2AuthorizationService查询服务器存储的令牌状态:

@Autowired
private OAuth2AuthorizationService authorizationService;

private AuthenticationProvider getIntrospectionAuthenticationProvider() {
    return new AuthenticationProvider() {
        @Override
        public Authentication authenticate(Authentication authentication) throws AuthenticationException {
            OAuth2TokenIntrospectionAuthenticationToken introspectionToken = 
                (OAuth2TokenIntrospectionAuthenticationToken) authentication;
            String token = introspectionToken.getToken();

            // 查询令牌是否存在且未过期
            OAuth2Authorization authorization = authorizationService.findByToken(
                token, OAuth2TokenType.ACCESS_TOKEN
            );
            
            Map<String, Object> attributes = new HashMap<>();
            if (authorization == null || authorization.getAccessToken().isExpired()) {
                attributes.put("active", false);
            } else {
                attributes.put("active", true);
                attributes.put("sub", authorization.getPrincipalName());
                // 可添加更多令牌属性,比如scope、exp等
            }

            return new OAuth2TokenIntrospectionAuthenticationToken(attributes);
        }

        @Override
        public boolean supports(Class<?> authentication) {
            return OAuth2TokenIntrospectionAuthenticationToken.class.isAssignableFrom(authentication);
        }
    };
}

关键说明

  • 必须通过authorizeHttpRequests.permitAll()放开/oauth2/introspect的访问限制,否则默认的客户端认证过滤器会直接返回401。
  • 利用OAuth2AuthorizationService可以直接从授权服务器的存储中查询令牌状态,确保校验逻辑的准确性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 00:52:55