Рубрики
Без рубрики

Как отключить Swagger-ui в производстве

Пользовательский интерфейс Swagger может быть очень полезен во время разработки, но может представлять угрозу безопасности в производстве. Мы смотрим, как сделать так, чтобы он не остался случайно доступным.

Автор оригинала: Cristian Stancalau.

1. Обзор

Пользовательский интерфейс Swagger позволяет нам просматривать информацию о наших сервисах REST. Это может быть очень удобно для развития. Однако из соображений безопасности мы можем не допустить такого поведения в нашей общественной среде.

В этом коротком уроке мы рассмотрим как | отключить Swagger в производстве .

2. Конфигурация Чванства

Чтобы настроить Swagger с помощью Spring , мы определяем его в конфигурационном бобе.

Давайте создадим класс SwaggerConfig :

@Configuration
@EnableSwagger2
public class SwaggerConfig implements WebMvcConfigurer {

    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2).select()
                .apis(RequestHandlerSelectors.basePackage("com.baeldung"))
                .paths(PathSelectors.regex("/.*"))
                .build();
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
    }
}

По умолчанию этот компонент конфигурации всегда вводится в наш контекст Spring. Таким образом, Swagger становится доступным для всех сред.

Чтобы отключить Swagger в производстве, давайте переключим, вводится ли этот компонент конфигурации.

3. Использование Пружинных Профилей

Весной мы можем использовать аннотацию @Profile, чтобы включить или отключить инъекцию бобов.

Давайте попробуем использовать выражение SpEL , чтобы соответствовать профилю “swagger” , но не профилю “prod” :

@Profile({"!prod && swagger"})

Это заставляет нас быть откровенными в отношении среды, в которой мы хотим активировать Swagger. Это также помогает предотвратить случайное включение его в производстве.

Мы можем добавить аннотацию к нашей конфигурации:

@Configuration 
@Profile({"!prod && swagger"})
@EnableSwagger2 
public class SwaggerConfig implements WebMvcConfigurer {
    ...
}

Теперь давайте проверим, что это работает, запустив наше приложение с различными настройками для свойства spring.profiles.active :

  -Dspring.profiles.active=prod // Swagger is disabled

  -Dspring.profiles.active=prod,anyOther // Swagger is disabled

  -Dspring.profiles.active=swagger // Swagger is enabled

  -Dspring.profiles.active=swagger,anyOtherNotProd // Swagger is enabled

  none // Swagger is disabled

4. Использование условных выражений

Пружинные профили могут быть слишком крупнозернистым решением для переключения функций. Такой подход может привести к ошибкам конфигурации и длинным, неуправляемым спискам профилей.

В качестве альтернативы мы можем использовать @ConditionalOnExpression , который позволяет указать пользовательские свойства для включения компонента:

@Configuration
@ConditionalOnExpression(value = "${useSwagger:false}")
@EnableSwagger2
public class SwaggerConfig implements WebMvcConfigurer {
    ...
}

Если свойство ” use Swagger ” отсутствует, то по умолчанию здесь используется значение false .

Чтобы проверить это, мы можем либо установить свойство в application.properties (или application.yaml ) файл, или установить его в качестве опции виртуальной машины:

-DuseSwagger=true

Мы должны отметить, что этот пример не включает в себя никакого способа гарантировать, что наш производственный экземпляр не может случайно иметь useSwagger установлен в true .

5. Избегание Подводных камней

Если включение Swagger является проблемой безопасности, то нам нужно выбрать стратегию, которая не допускает ошибок, но проста в использовании.

Некоторые выражения SpEL могут работать против этих целей, когда мы используем @Profile :

@Profile({"!prod"}) // Leaves Swagger enabled by default with no way to disable it in other profiles
@Profile({"swagger"}) // Allows activating Swagger in prod as well
@Profile({"!prod", "swagger"}) // Equivalent to {"!prod || swagger"} so it's worse than {"!prod"} as it provides a way to activate Swagger in prod too

Вот почему наш @Profile пример используется:

@Profile({"!prod && swagger"})

Это решение, вероятно, является самым строгим, так как оно делает Swagger отключенным по умолчанию и гарантирует, что он не может быть включен в “prod” .

6. Заключение

В этой статье мы рассмотрели решения для отключения Swagger в производстве.

Мы рассмотрели, как переключить компонент, который включает Swagger, с помощью аннотаций @Profile и @ConditionalOnExpression . Мы также рассмотрели способы защиты от неправильной конфигурации и нежелательных значений по умолчанию.

Как всегда, пример кода из этой статьи можно найти на GitHub .