1. 概述
Swagger 用户界面允許我們查看有關我們的 REST 服務的信息。這對於開發非常方便。然而,由於安全考慮,我們可能不希望在我們的公共環境中允許這種行為。
在本簡短教程中,我們將學習如何在生產環境中關閉 Swagger。
2. Swagger 配置
使用 SpringDoc 設置 Swagger,我們將其定義在配置 Bean 中。
讓我們創建一個 SwaggerConfig 類:
@Configuration
public class SwaggerConfig {
@Bean
public OpenAPI openAPI() {
return new OpenAPI().info(new Info().title("SpringDoc Disable SwaggerUI 示例")
.description("SpringDoc Disable SwaggerUI 應用")
.version("v0.0.1"));
}
}
默認情況下,此配置 Bean 始終注入到我們的 Spring 上下文中。因此,Swagger 對所有環境都可用。
要禁用生產環境中的 Swagger,讓我們切換此配置 Bean 是否注入。
3. 使用 Spring 配置文件
在 Spring 中,我們可以使用 @Profile 註解來啓用或禁用 Bean 的注入。
讓我們嘗試使用 SpEL 表達式來匹配 “swagger” 配置文件,但不匹配 “prod” 配置文件:
@Profile({"!prod && swagger"})
這迫使我們明確説明我們想要激活 Swagger 的環境。它也有助於防止在生產環境中意外啓用它。
我們可以將該註解添加到我們的配置中:
@Configuration
@Profile({"!prod && swagger"})
public class SwaggerConfig {
...
}
現在,讓我們測試它是否有效,通過使用不同的設置啓動我們的應用程序,用於 spring.profiles.active 屬性:
-Dspring.profiles.active=prod // Swagger 已禁用
-Dspring.profiles.active=prod,anyOther // Swagger 已禁用
-Dspring.profiles.active=swagger // Swagger 已啓用
-Dspring.profiles.active=swagger,anyOtherNotProd // Swagger 已啓用
none // Swagger 已禁用
4. 使用條件語句
Spring Profiles 對於功能開關來説可能過於粗粒度。這種方法可能導致配置錯誤和龐大、難以管理的 profiles 列表。
作為替代方案,我們可以使用 @ConditionalOnExpression,允許指定自定義屬性以啓用 Bean:
@Configuration
@ConditionalOnExpression(value = "${useSwagger:false}")
public class SwaggerConfig {
...
}
如果“useSwagger” 屬性不存在,則默認值為 false。
要測試此功能,我們可以通過在 application.properties (或 application.yaml) 文件中設置屬性,或將其作為 VM 選項設置來完成:
-DuseSwagger=true
請注意,此示例不包括任何方法來保證我們的生產實例不能意外地將 useSwagger 設置為 true。
5. 避免潛在問題
如果啓用 Swagger 存在安全問題,那麼我們需要選擇一種既安全又易於使用的策略。
某些 SpEL 表達式在結合使用 @Profile 時可能會與這些目標相悖。
@Profile({"!prod"}) // 默認啓用 Swagger,且沒有其他 Profile 中的禁用方式
@Profile({"swagger"}) // 允許在 prod 環境中啓用 Swagger
@Profile({"!prod", "swagger"}) // 等價於 {"!prod || swagger"},比 {"!prod"} 更加糟糕,因為它也提供了在 prod 環境中啓用 Swagger 的方式
這就是我們使用的 @Profile 示例的原因:
@Profile({"!prod && swagger"})
這個解決方案可能是最嚴格的,因為它默認禁用 Swagger,並保證它不能在 “prod” 環境中啓用。
6. 結論
在本文中,我們探討了在生產環境中禁用 Swagger 的解決方案。
我們研究了通過 @Profile 和 @ConditionalOnExpression 註解來切換啓用 Swagger 的 Bean。我們還考慮瞭如何防止配置錯誤和不希望出現的默認設置。