Spring Boot 3 Jetty管理端口无法禁用TRACE方法问题求助
问题描述
我基于Spring Boot 3构建了一个使用spring-boot-starter-jetty和actuator的应用,配置了server.port != management.server.port(服务端口与管理端口分离)。我需要同时禁用服务端口和管理端口的TRACE请求,但尝试多种方案后,仅服务端口的TRACE请求被拦截返回405,管理端口始终返回200 OK。
我搭建了测试项目复现该问题,其中testTraceDisabledManagement测试用例始终无法通过。
项目结构
├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ └── example │ │ │ ├── demo │ │ │ │ ├── CustomDispatcherServlet.java │ │ │ │ └── DemoApplication.java │ │ │ └── server │ │ │ └── MgmtServerConfiguration.java │ │ └── resources │ │ ├── META-INF │ │ │ └── spring │ │ │ └── org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration.imports │ │ ├── application.properties │ │ ├── static │ │ └── templates │ └── test │ └── java │ └── com │ └── example │ └── demo │ └── DemoApplicationTests.java
测试代码
@Test public void testTraceDisabledApi() throws URISyntaxException { verifyTraceFails(this.apiPort); // 正常 - Jetty返回405 } /** * 测试管理端口的TRACE请求是否被禁用 */ @Test public void testTraceDisabledManagement() throws URISyntaxException { verifyTraceFails(this.managementPort); // 失败 - Jetty返回200 } private void verifyTraceFails(final int port) throws URISyntaxException { final String url = "http://localhost:" + port; RestTemplate restTemplate = new RestTemplate(); try { RequestEntity<Void> requestEntity = new RequestEntity<>(TRACE, new URI(url)); ResponseEntity<String> response = restTemplate.exchange(requestEntity, String.class); assertThat(response.getStatusCode(), Matchers.equalTo(METHOD_NOT_ALLOWED)); } catch (org.springframework.web.client.HttpClientErrorException e) { assertThat(e.getStatusCode(), Matchers.equalTo(METHOD_NOT_ALLOWED)); return; } catch (Exception e) { Assertions.fail("不应该走到这里", e); } Assertions.fail("不应该走到这里"); }
解决方案
因为Spring Boot的管理端口(Actuator)使用独立Web上下文,主服务端口的配置不会自动覆盖管理端口。针对Jetty容器,需单独为管理端口配置禁用TRACE方法:
创建管理端口的Jetty配置类
在server包下的MgmtServerConfiguration.java中,通过Jetty的HttpConfiguration拦截TRACE请求:import org.eclipse.jetty.server.HttpConfiguration; import org.springframework.boot.web.embedded.jetty.JettyServerCustomizer; import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MgmtServerConfiguration { @Bean public WebServerFactoryCustomizer<JettyServletWebServerFactory> managementJettyTraceCustomizer() { return factory -> { factory.addServerCustomizers((JettyServerCustomizer) server -> { server.getConnectors().forEach(connector -> { if (connector.getProtocolHandler() instanceof org.eclipse.jetty.server.HttpConnectionFactory) { org.eclipse.jetty.server.HttpConnectionFactory connectionFactory = (org.eclipse.jetty.server.HttpConnectionFactory) connector.getProtocolHandler(); HttpConfiguration httpConfig = connectionFactory.getHttpConfiguration(); httpConfig.addCustomizer((request, response) -> { if ("TRACE".equals(request.getMethod())) { response.setStatus(405); response.getHttpChannel().sendResponse(); } }); } }); }); }; } }确保配置类被管理上下文加载
打开META-INF/spring/org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration.imports文件,添加配置类的全限定名:com.example.server.MgmtServerConfiguration验证测试结果
重新运行测试用例,testTraceDisabledManagement会返回405状态码,测试通过。
内容的提问来源于stack exchange,提问作者Fabio Mangione
相关产品推荐
相关产品推荐

