如何让Spring Boot 3 Actuator识别X-Forwarded-Prefix请求头?
Spring Boot 3 Actuator 适配 X-Forwarded-Prefix 生成正确链接的解决方案
问题核心
Spring Boot 3中,仅通过添加ForwardedHeaderFilter无法让Actuator的链接生成逻辑感知到代理传递的X-Forwarded-Prefix头,且原Spring Boot 2.7基于ManagementContextFactory的 workaround 因类结构变更失效,需调整配置或自定义逻辑解决。
可行解决方案
1. 配置ForwardedHeaderFilter并调整Actuator路径映射
确保过滤器正确作用于Actuator路径,同时配合框架的转发头策略:
- 注册优先级靠前的ForwardedHeaderFilter:
import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.filter.ForwardedHeaderFilter; @Configuration public class ProxyConfig { @Bean public FilterRegistrationBean<ForwardedHeaderFilter> forwardedHeaderFilter() { FilterRegistrationBean<ForwardedHeaderFilter> registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new ForwardedHeaderFilter()); registrationBean.addUrlPatterns("/management/*"); registrationBean.setOrder(-100); // 确保在其他过滤器前执行 return registrationBean; } }
- 在
application.yml中配置Actuator与服务器属性:
server: forward-headers-strategy: framework # 明确使用框架处理转发头 management: server: port: 8081 base-path: /management endpoints: web: base-path: / # 将端点基础路径设为根,配合代理前缀拼接 exposure: include: "*"
2. 自定义EndpointLinksResolver覆盖链接生成逻辑
若上述配置仍不生效,可自定义链接解析器,手动注入X-Forwarded-Prefix值:
import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver; import org.springframework.boot.actuate.endpoint.web.WebEndpointResponse; import org.springframework.boot.actuate.endpoint.web.annotation.EndpointWebExtension; import org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointWebExtension; import org.springframework.boot.actuate.endpoint.web.Link; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import jakarta.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.List; import java.util.Map; @Configuration public class ActuatorLinkConfig { @Bean public EndpointLinksResolver customEndpointLinksResolver(List<ServletEndpointWebExtension> servletExtensions, List<EndpointWebExtension<?>> webExtensions) { return new EndpointLinksResolver(servletExtensions, webExtensions) { @Override public WebEndpointResponse<Map<String, Link>> links() { WebEndpointResponse<Map<String, Link>> originalResponse = super.links(); HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); String forwardedPrefix = request.getHeader("X-Forwarded-Prefix"); if (forwardedPrefix != null && !forwardedPrefix.isEmpty()) { Map<String, Link> modifiedLinks = new HashMap<>(originalResponse.getBody()); modifiedLinks.replaceAll((key, link) -> { String originalHref = link.getHref(); String newHref = forwardedPrefix + "/management" + originalHref.substring(originalHref.indexOf("/", 1)); return Link.of(newHref); }); return new WebEndpointResponse<>(modifiedLinks, originalResponse.getStatus()); } return originalResponse; } }; } }
3. 验证效果
启动应用后通过代理访问https://www.company.com/management,查看返回JSON的_links节点,确认所有链接的href已包含/service/management前缀。
内容的提问来源于stack exchange,提问作者Johan
相关产品推荐
相关产品推荐

