1. 概述

Swagger UI 能让我们直观地查看 REST 接口的文档信息,在开发阶段非常方便。✅
但出于安全考虑,我们通常不希望在生产环境暴露这些接口信息。❌

本文将介绍几种简单粗暴又靠谱的方式,教你如何在生产环境中彻底关闭 Swagger UI,避免踩坑。


2. Swagger 基础配置

使用 SpringDoc 集成 Swagger 时,通常会通过一个配置类来定义 OpenAPI 信息。

我们创建一个 SwaggerConfig 类:

@Configuration
public class SwaggerConfig {
    
    @Bean
    public OpenAPI openAPI() {
        return new OpenAPI().info(new Info().title("SpringDoc Disable SwaggerUI example")
            .description("SpringDoc Disable SwaggerUI application")
            .version("v0.0.1"));
    }
}

⚠️ 默认情况下,这个配置类会被加载到 Spring 容器中,意味着 Swagger 在所有环境下都可用。

要想只在非生产环境启用,就必须控制这个配置类的加载时机。


3. 使用 Spring Profiles 控制加载

Spring 提供了 @Profile 注解,可以根据激活的 profile 决定是否加载某个 Bean。

我们希望:
✅ 只有明确指定时才启用 Swagger
❌ 生产环境(prod)绝对不能开启

因此,使用 SpEL 表达式进行精确控制:

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

将该注解加到配置类上:

@Configuration 
@Profile({"!prod && swagger"})
public class SwaggerConfig {
    // 同上
}

效果验证

启动应用时通过 spring.profiles.active 参数测试不同组合:

-Dspring.profiles.active=prod                          // ❌ Swagger 禁用
-Dspring.profiles.active=prod,other                   // ❌ Swagger 禁用
-Dspring.profiles.active=swagger                      // ✅ Swagger 启用
-Dspring.profiles.active=swagger,dev                  // ✅ Swagger 启用
没有设置 active profile                                // ❌ 默认禁用

✅ 这种方式做到了:

  • 默认关闭(安全兜底)
  • 必须显式启用(防误操作)
  • 生产环境无法绕过(硬性限制)

4. 使用条件化注解 @ConditionalOnExpression

有时候用 Profile 控制显得太重,尤其是当项目中 profile 数量多、管理混乱时,容易出错。

更灵活的方式是使用 @ConditionalOnExpression,通过自定义属性控制:

@Configuration
@ConditionalOnExpression("${useSwagger:false}")
public class SwaggerConfig {
    // 同上
}

说明:

  • ${useSwagger:false} 表示:读取 useSwagger 属性,若不存在则默认为 false
  • 只有当该值为 true 时,Swagger 配置才会被加载

启用方式(任选其一):

application.properties 中设置:

useSwagger=true

或通过 JVM 参数:

-DuseSwagger=true

⚠️ 注意:这种方式虽然灵活,但无法从根本上阻止生产环境误设为 true,存在安全隐患。
如果你的团队流程不够严谨,建议慎用。


5. 常见踩坑点与避坑指南

以下是几个看似合理但实际上有问题的写法,务必避开:

❌ 错误写法 1:仅排除 prod

@Profile({"!prod"})

问题:只要不是 prod 环境就自动开启,其他环境可能也不该开(比如预发),且无法显式控制。

❌ 错误写法 2:只看是否包含 swagger

@Profile({"swagger"})

问题:如果 prod 和 swagger 同时激活(如 -Dspring.profiles.active=prod,swagger),Swagger 依然会启用!💣

❌ 错误写法 3:使用或逻辑

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

等价于 !prod OR swagger —— 只要 profile 是 swagger,哪怕同时是 prod,也会启用!比上面更危险。

✅ 正确姿势(推荐)

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

含义:必须同时满足“不是 prod” “包含 swagger” 才启用。

🎯 效果:

  • 默认关闭
  • 显式启用
  • 生产环境铁定关

这才是真正“防手残”的设计。


6. 总结

本文介绍了两种主流方式来在生产环境关闭 Swagger UI:

方式 优点 缺点 推荐场景
@Profile("!prod && swagger") 安全性强,逻辑清晰 需规范 profile 使用 ✅ 多数项目首选
@ConditionalOnExpression 灵活,可动态控制 易被误配,安全性弱 ⚠️ 内部系统或测试环境

📌 最佳实践建议:

使用 @Profile({"!prod && swagger"}),做到默认关闭、显式开启、生产封死。

所有示例代码已上传至 GitHub:
👉 https://github.com/eugenp/tutorials/tree/master/spring-web-modules/spring-rest-http-2


原始标题:How to Turn Off Swagger-ui in Production