使 Spring Boot 2.7.x致动器知道X-转发-前缀标头?

ssgvzors  于 2022-12-23  发布在  Spring
关注(0)|答案(2)|浏览(163)

我们正在使用Sping Boot 2.7.0和spring-boot-starter-actuator,我们在/management上下文路径下的端口8081上公开了spring-boot-starter-actuator。代理设置了几个X-Forwarded-*标头,包括设置为/serviceX-Forwarded-Prefix标头。但是当导航到https://www.company.com/management时,返回的是以下内容:

{
    "_links": {
        "self": {
            "href": "https://www.company.com/management",
            "templated": false
        },
        "beans": {
            "href": "https://www.company.com/management/beans",
            "templated": false
        },
        "caches-cache": {
            "href": "https://www.company.com/management/caches/{cache}",
            "templated": true
        },
        "caches": {
            "href": "https://www.company.com/management/caches",
            "templated": false
        },
        "health": {
            "href": "https://www.company.com/management/health",
            "templated": false
        },
        "health-path": {
            "href": "https://www.company.com/management/health/{*path}",
            "templated": true
        },
        "info": {
            "href": "https://www.company.com/management/info",
            "templated": false
        },
        "conditions": {
            "href": "https://www.company.com/management/conditions",
            "templated": false
        },
        "configprops": {
            "href": "https://www.company.com/management/configprops",
            "templated": false
        },
        "configprops-prefix": {
            "href": "https://www.company.com/management/configprops/{prefix}",
            "templated": true
        },
        "env": {
            "href": "https://www.company.com/management/env",
            "templated": false
        },
        "env-toMatch": {
            "href": "https://www.company.com/management/env/{toMatch}",
            "templated": true
        },
        "integrationgraph": {
            "href": "https://www.company.com/management/integrationgraph",
            "templated": false
        },
        "loggers": {
            "href": "https://www.company.com/management/loggers",
            "templated": false
        },
        "loggers-name": {
            "href": "https://www.company.com/management/loggers/{name}",
            "templated": true
        },
        "heapdump": {
            "href": "https://www.company.com/management/heapdump",
            "templated": false
        },
        "threaddump": {
            "href": "https://www.company.com/management/threaddump",
            "templated": false
        },
        "metrics-requiredMetricName": {
            "href": "https://www.company.com/management/metrics/{requiredMetricName}",
            "templated": true
        },
        "metrics": {
            "href": "https://www.company.com/management/metrics",
            "templated": false
        },
        "scheduledtasks": {
            "href": "https://www.company.com/management/scheduledtasks",
            "templated": false
        },
        "sessions-sessionId": {
            "href": "https://www.company.com/management/sessions/{sessionId}",
            "templated": true
        },
        "sessions": {
            "href": "https://www.company.com/management/sessions",
            "templated": false
        },
        "mappings": {
            "href": "https://www.company.com/management/mappings",
            "templated": false
        },
        "refresh": {
            "href": "https://www.company.com/management/refresh",
            "templated": false
        },
        "features": {
            "href": "https://www.company.com/management/features",
            "templated": false
        },
        "traces": {
            "href": "https://www.company.com/management/traces",
            "templated": false
        }
    }
}

由于提供了X-Forwarded-Prefix头,我希望响应中的href以https://www.company.com/service开头,但事实并非如此。我尝试添加ForwardedHeaderFilter,如下所示:

@Bean
public FilterRegistrationBean<ForwardedHeaderFilter> forwardedHeaderFilterFilterRegistrationBean() {
    ForwardedHeaderFilter forwardedHeaderFilter = new ForwardedHeaderFilter();
    FilterRegistrationBean<ForwardedHeaderFilter> bean = new FilterRegistrationBean<>(forwardedHeaderFilter);
    bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
    return bean;
}

但这没什么区别。
当生成到代理后面的端点的链接时,如何让actuator考虑X-Forwarded-Prefix头?

rdrgkggo

rdrgkggo1#

我遇到了同样的问题。我发现如果管理端口不同,ManagementContextAutoConfiguration使用单独的WebApplicationContext。这就是为什么声明ForwardedHeaderFilter没有效果。可能是Spring执行器有问题。我做了这个黑客,它似乎是工作。但我希望有人会找到更好的解决方案。

@Component
@ConditionalOnManagementPort(ManagementPortType.DIFFERENT)
public class ManagementContextFactoryBeanPostProcessor
        implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName)
            throws BeansException {
        if (bean instanceof ManagementContextFactory managementContextFactory) {
            return (ManagementContextFactory) (parent, configurationClasses) -> {
                var context = managementContextFactory.createManagementContext(parent, configurationClasses);
                if (context instanceof GenericWebApplicationContext genericWebApplicationContext) {
                    genericWebApplicationContext.registerBean(ForwardedHeaderFilterRegistrationBean.class);
                }
                return context;
            };
        }
        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    public static class ForwardedHeaderFilterRegistrationBean
            extends FilterRegistrationBean<ForwardedHeaderFilter> {

        public ForwardedHeaderFilterRegistrationBean() {
            setFilter(new ForwardedHeaderFilter());
            setOrder(Ordered.HIGHEST_PRECEDENCE);
        }

    }

}
kqhtkvqz

kqhtkvqz2#

如果您使用Spring Security,则可以通过端点安全配置添加ForwardedHeaderFilter,如下所示:

@Bean
public WebSecurityConfigurerAdapter webSecurityConfigurerAdapter() {
    return new WebSecurityConfigurerAdapter() {
        @Override
        protected void configure(HttpSecurity http) {
            http.requestMatcher(EndpointRequest.toAnyEndpoint())
                .addFilterBefore(new ForwardedHeaderFilter(), HeaderWriterFilter.class);
        }
    };
}

相关问题