Мы используем SpringBoot и SpringFox, используя @EnableSwagger2
для предоставления документации по API swagger-ui.html
(она нам не нужна для автоматизации клиентского кода, как документация и тестовый интерфейс).
Можно ли запустить все связанные с Swagger конечные точки под другим портом (например, портом управления загрузкой / мониторинга пружины), чем основное приложение?
Я немного исследовал, но не нашел способа сделать это в конфигурации swagger's / springfox. Есть ли весенний способ сделать это?
Всего 2 ответа
Да, есть Spring способ сделать это:
Чтобы добавить порт к встроенному серверу, необходимо настроить дополнительный соединитель. Мы сделаем это, предоставив пользовательский WebServerFactoryCustomizer:
@Component
public class TomcatContainerCustomizer implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {
@Value("${swagger.port}")
private int swaggerPort;
@Override
public void customize(TomcatServletWebServerFactory factory) {
Connector swaggerConnector = new Connector();
swaggerConnector.setPort(swaggerPort);
factory.addAdditionalTomcatConnectors(swaggerConnector);
}
}
Теперь Tomcat прослушивает два порта, но обслуживает один и тот же контент на обоих. Нам нужно отфильтровать это.
Добавить фильтр сервлета довольно просто с FilterRegistrationBean. Это может быть создано где угодно, я добавил это непосредственно к TomcatContainerCustomizer.
@Component
public class TomcatContainerCustomizer implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {
@Value("${swagger.port}")
private int swaggerPort;
@Value("${swagger.paths}")
private List<String> swaggerPaths;
@Override
public void customize(TomcatServletWebServerFactory factory) {
Connector swaggerConnector = new Connector();
swaggerConnector.setPort(swaggerPort);
factory.addAdditionalTomcatConnectors(swaggerConnector);
}
@Bean
public FilterRegistrationBean<SwaggerFilter> swaggerFilterRegistrationBean() {
FilterRegistrationBean<SwaggerFilter> filterRegistrationBean = new FilterRegistrationBean<>();
filterRegistrationBean.setFilter(new SwaggerFilter());
filterRegistrationBean.setOrder(-100);
filterRegistrationBean.setName("SwaggerFilter");
return filterRegistrationBean;
}
private class SwaggerFilter extends OncePerRequestFilter {
private AntPathMatcher pathMatcher = new AntPathMatcher();
@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
FilterChain filterChain) throws ServletException, IOException {
boolean isSwaggerPath = swaggerPaths.stream()
.anyMatch(path -> pathMatcher.match(path, httpServletRequest.getServletPath()));
boolean isSwaggerPort = httpServletRequest.getLocalPort() == swaggerPort;
if(isSwaggerPath == isSwaggerPort) {
filterChain.doFilter(httpServletRequest, httpServletResponse);
} else {
httpServletResponse.sendError(404);
}
}
}
}
Свойства swagger.port
и swagger.paths
настраиваются в application.yaml:
server.port: 8080
swagger:
port: 8088
paths: |
/swagger-ui.html,
/webjars/springfox-swagger-ui/**/*,
/swagger-resources,
/swagger-resources/**/*,
/v2/api-docs
Пока все хорошо: swagger-ui обслуживается через порт 8088, наш API на 8080. Но есть проблема: когда мы пытаемся подключиться к API от swagger-ui, запросы отправляются на 8088 8080.
Swagger предполагает, что API работает на том же порту, что и Swagger-UI. Нам нужно явно указать порт:
@Value("${server.port}")
private int serverPort;
@Bean
public Docket docket() {
return new Docket(DocumentationType.SWAGGER_2)
.host("localhost:" + serverPort);
}
И последняя проблема: поскольку пользовательский интерфейс работает на порте, отличном от API, запросы считаются перекрестными. Нам нужно разблокировать их. Это можно сделать глобально:
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**/*").allowedOrigins("http://localhost:" + swaggerPort);
}
};
}
или добавив аннотации к контроллерам:
@CrossOrigin(origins = "http://localhost:${swagger.port}")
Используемые версии: SpringBoot 2.2.2.RELEASE, springfox-swagger2 2.9.2
Рабочий пример см. Https://github.com/mafor/swagger-ui-port.
Я так не думаю. Когда вы устанавливаете порт управления Spring Boot (management.server.port), запускается второй сервер приложений для обслуживания исполнительных механизмов. Насколько я знаю, нет никакой возможности (кроме пользовательских конечных точек привода) публиковать что-либо на этом сервере.
Какой именно ваш вариант использования? Вы хотите запретить доступ к Swagger в рабочей среде или для пользователей, не прошедших проверку подлинности?