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

两种OAuth2AccessToken获取方式的过期问题及解决方案咨询

问题分析与解决方案

问题原因

第一种方式自动刷新的原理

@RegisteredOAuth2AuthorizedClient注解由Spring Security的OAuth2AuthorizedClientArgumentResolver负责解析,这个解析器内部会通过OAuth2AuthorizedClientManager完成令牌有效性校验:

  • 检测到令牌过期时,会自动调用配置好的刷新逻辑获取新令牌
  • 但该解析器仅作用于Controller方法参数注入场景,无法在过滤器/拦截器中直接复用这一逻辑

第二种方式返回旧令牌的原因

OAuth2AuthorizedClientService的核心职责是持久化和读取授权客户端数据,它本身不具备令牌过期校验和自动刷新能力:

  • 调用loadAuthorizedClient()时,只会直接返回存储中已有的旧数据
  • 即使令牌已过期,也不会主动触发刷新流程,所以拿到的始终是过期令牌

解决方案:在过滤器中集成令牌自动刷新逻辑

要在过滤器中实现和@RegisteredOAuth2AuthorizedClient一致的自动刷新效果,需直接使用OAuth2AuthorizedClientManager管理授权客户端,而非直接调用OAuth2AuthorizedClientService。

步骤1:配置OAuth2AuthorizedClientManager

在配置类中定义OAuth2AuthorizedClientManager的Bean,它会自动整合令牌刷新逻辑:

@Configuration
public class OAuth2ClientConfig {

    @Bean
    public OAuth2AuthorizedClientManager authorizedClientManager(
            ClientRegistrationRepository clientRegistrationRepository,
            OAuth2AuthorizedClientService authorizedClientService) {

        OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
                .authorizationCode()
                .refreshToken() // 启用刷新令牌支持
                .build();

        DefaultOAuth2AuthorizedClientManager authorizedClientManager = new DefaultOAuth2AuthorizedClientManager(
                clientRegistrationRepository, authorizedClientService);
        authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);

        return authorizedClientManager;
    }
}

步骤2:改造过滤器使用OAuth2AuthorizedClientManager

修改过滤器,注入OAuth2AuthorizedClientManager,通过它获取授权客户端,自动处理令牌过期刷新:

@Component
public class TestFilter implements Filter {

    private final OAuth2AuthorizedClientManager authorizedClientManager;

    // 构造注入(推荐替代@Autowired)
    public TestFilter(OAuth2AuthorizedClientManager authorizedClientManager) {
        this.authorizedClientManager = authorizedClientManager;
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        OAuth2AuthenticationToken authentication = (OAuth2AuthenticationToken) SecurityContextHolder.getContext().getAuthentication();

        // 构建客户端授权请求
        OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId("azure")
                .principal(authentication)
                .build();

        // 由manager处理令牌校验与刷新,返回有效令牌
        OAuth2AuthorizedClient authorizedClient = authorizedClientManager.authorize(authorizeRequest);

        if (authorizedClient != null) {
            servletRequest.setAttribute("access-token", authorizedClient.getAccessToken());
        }
        
        filterChain.doFilter(servletRequest, servletResponse);
    }
}

关键说明

  • OAuth2AuthorizedClientManager会自动检查令牌是否过期,若过期且存在有效刷新令牌,会自动调用授权服务器刷新令牌,并将新令牌更新到OAuth2AuthorizedClientService的存储中
  • 这种方式和@RegisteredOAuth2AuthorizedClient使用同一套逻辑,保证了令牌处理的一致性
  • 可将该过滤器封装为通用组件,在多服务中直接复用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 14:32:20