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

如何用Spring Boot Actuator获取OAuth端点HTTP追踪及JWT验证耗时?

解决方案

方法一:扩展Actuator的HttpExchange追踪范围

从Spring Boot 2.4起,/httptrace端点被/actuator/httpexchanges替代,默认仅追踪经过DispatcherServlet的请求,而Spring Security的OAuth端点(/authorize、/token)由Filter链处理、不走DispatcherServlet,因此需要自定义配置捕获这类请求:

  1. 自定义Servlet Filter,拦截所有请求并提交到HttpExchangeRepository:
import org.springframework.boot.actuate.web.exchanges.HttpExchange;
import org.springframework.boot.actuate.web.exchanges.HttpExchangeRepository;
import org.springframework.boot.web.servlet.filter.OrderedFilter;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class AllRequestTraceFilter implements Filter, OrderedFilter {

    private final HttpExchangeRepository repository;

    public AllRequestTraceFilter(HttpExchangeRepository repository) {
        this.repository = repository;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        if (request instanceof HttpServletRequest && response instanceof HttpServletResponse) {
            HttpServletRequest httpRequest = (HttpServletRequest) request;
            HttpServletResponse httpResponse = (HttpServletResponse) response;
            long start = System.currentTimeMillis();
            try {
                chain.doFilter(request, response);
            } finally {
                long duration = System.currentTimeMillis() - start;
                this.repository.add(new HttpExchange(httpRequest, httpResponse, duration, null));
            }
        } else {
            chain.doFilter(request, response);
        }
    }

    // 设置Filter顺序为最高优先级,确保在Spring Security过滤器前捕获请求
    @Override
    public int getOrder() {
        return OrderedFilter.HIGHEST_PRECEDENCE;
    }
}
  1. 启用Actuator的httpexchanges端点:
    在application.yml中配置:
management:
  endpoints:
    web:
      exposure:
        include: httpexchanges
  endpoint:
    httpexchanges:
      enabled: true

访问/actuator/httpexchanges即可查看包含OAuth端点在内的所有请求追踪,其中包含请求耗时数据。

方法二:用Micrometer监控JWT验证耗时

通过Micrometer自定义Timer,精准统计JWT令牌验证的时间:

  1. 自定义计时版的BearerToken过滤器:
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import org.springframework.security.web.authentication.www.BearerTokenAuthenticationFilter;
import org.springframework.stereotype.Component;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class TimedBearerTokenFilter extends BearerTokenAuthenticationFilter {

    private final Timer timer;

    public TimedBearerTokenFilter(MeterRegistry registry) {
        super(null); // 根据实际项目的构造参数调整
        this.timer = Timer.builder("jwt.validation.duration")
                .description("JWT令牌验证耗时统计")
                .register(registry);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        timer.record(() -> {
            try {
                super.doFilterInternal(request, response, filterChain);
            } catch (ServletException | IOException e) {
                throw new RuntimeException(e);
            }
        });
    }
}
  1. 在Security配置中替换默认过滤器:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

@Configuration
public class SecurityConfig {

    private final TimedBearerTokenFilter timedBearerTokenFilter;

    public SecurityConfig(TimedBearerTokenFilter timedBearerTokenFilter) {
        this.timedBearerTokenFilter = timedBearerTokenFilter;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
                .oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt))
                .addFilterBefore(timedBearerTokenFilter, BasicAuthenticationFilter.class);
        return http.build();
    }
}
  1. 访问/actuator/metrics/jwt.validation.duration,即可查看JWT验证的耗时统计(平均值、最大值等维度数据)。

方法三:自定义日志记录耗时

如果不需要集成到Actuator,可直接通过日志输出JWT验证时间:

  1. 包装JwtDecoder添加计时逻辑:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.stereotype.Component;

@Component
public class TimedJwtDecoder implements JwtDecoder {

    private final JwtDecoder delegate;
    private final Logger logger = LoggerFactory.getLogger(TimedJwtDecoder.class);

    public TimedJwtDecoder(JwtDecoder delegate) {
        this.delegate = delegate;
    }

    @Override
    public Jwt decode(String token) {
        long start = System.currentTimeMillis();
        try {
            return delegate.decode(token);
        } finally {
            long duration = System.currentTimeMillis() - start;
            logger.info("JWT令牌验证耗时:{} ms", duration);
        }
    }
}
  1. 在配置中使用自定义Decoder:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;

@Configuration
public class JwtConfig {

    @Bean
    public JwtDecoder jwtDecoder() {
        NimbusJwtDecoder decoder = NimbusJwtDecoder.withJwkSetUri("你的JWK地址").build();
        return new TimedJwtDecoder(decoder);
    }
}

每次JWT验证时,日志中会输出具体耗时。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 13:20:38