«1. Обзор

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

В этом коротком руководстве мы рассмотрим, как отключить Swagger в рабочей среде.

2. Конфигурация Swagger

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

Давайте создадим класс 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. Использование профилей Spring

В Spring мы можем использовать аннотацию @Profile для включения или отключения внедрения bean-компонентов.

Давайте попробуем использовать выражение 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. Использование условных выражений

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

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

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

Если свойство «useSwagger» отсутствует, значение по умолчанию здесь равно false.

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

-DuseSwagger=true

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

5. Как избежать ловушек

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

@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

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

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

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

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

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

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