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