Spring Boot Swagger 安全防护全解析:从旧版实践到官方规范
摘要
本文系统梳理 Swagger 安全防护的核心方案,涵盖旧版 Swagger(SpringFox)的swagger.basic
配置实践、官方推荐的 Spring Security 方案,以及多环境管理、反向代理过滤等全链路技术。结合权威文档,明确不同方案的适用版本与场景,助力开发者构建安全合规的 API 文档体系。
一、Swagger 安全问题背景
Swagger(或 SpringDoc OpenAPI)生成的 API 文档是开发者的 “利器”,但也可能成为攻击者的 “攻击地图”。未防护的 Swagger UI 会暴露以下风险:
- 接口信息泄露:所有接口路径、参数类型及权限要求被公开;
- 越权调用风险:攻击者可直接构造恶意请求调用敏感接口;
- 版本漏洞隐患:旧版 Swagger(如 SpringFox <3.0.0)存在 CVE-2020-8908(远程代码执行)等高危漏洞。
二、旧版 Swagger 的配置实践:swagger.basic
的适用场景
2.1 适用版本与实现逻辑
swagger.basic
配置常见于旧版 Swagger 集成方案(如 SpringFox 2.x),适用于早期 Spring Boot 项目(<2.6 版本)。其核心逻辑是通过自定义过滤器实现 Basic 认证,配置示例如下(application.yml
):
yaml
# 旧版SpringFox配置(非官方)
swagger: production: false # 是否为生产环境 basic: enable: true # 启用Basic认证 username: zhangsan # 认证用户名 password: 123 # 认证密码(明文存储,风险高)
2.2 局限性与风险
尽管swagger.basic
在早期项目中被广泛使用,但其存在以下缺陷:
- 不再维护:SpringFox 自 2020 年起停止更新,不兼容 Spring Boot 2.6 + 及以上版本;
- 安全隐患:密码以明文形式存储在配置文件中,易泄露;认证逻辑仅通过简单过滤器实现,未与 Spring Security 深度集成,防护能力弱;
- 官方不推荐:Spring Boot 官方已明确建议迁移至 SpringDoc OpenAPI(Swagger 3.x 官方实现)。
三、官方推荐方案:Spring Security 实现 Basic 认证
SpringDoc OpenAPI(Swagger 3.x 官方实现)是当前 Spring Boot 项目的最佳选择。其安全防护需通过Spring Security实现,这是 Spring 官方唯一推荐的方案。
3.1 核心依赖(Spring Boot 3.x+)
xml
<!-- Spring Security(安全核心) -->
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId>
</dependency> <!-- SpringDoc OpenAPI(Swagger 3.x) -->
<dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> <version>2.2.0</version> <!-- 2025年最新版,修复CVE-2023-25690 -->
</dependency>
3.2 核心配置类(Spring Security 集成)
通过 Spring Security 为 Swagger 路径(/swagger-ui/**
、/v3/api-docs/**
)添加 Basic 认证规则,仅授权用户可访问。配置示例如下:
java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain; @Configuration
@EnableWebSecurity
public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .csrf(csrf -> csrf.disable()) // 关闭CSRF(前后端分离场景) .authorizeHttpRequests(auth -> auth // Swagger路径需认证(触发Basic弹窗) .requestMatchers("/swagger-ui/**", "/v3/api-docs/**").authenticated() // 公共接口(如登录)无需认证 .requestMatchers("/api/auth/login").permitAll() // 其他接口默认认证 .anyRequest().authenticated() ) .httpBasic(); // 启用Basic认证 return http.build(); } @Bean public UserDetailsService userDetailsService(PasswordEncoder passwordEncoder) { // 配置认证用户(生产环境替换为数据库/LDAP) return new InMemoryUserDetailsManager( User.builder() .username("zhangsan") // 用户名 .password(passwordEncoder.encode("123")) // 密码(BCrypt加密) .roles("DEVELOPER") // 角色 .build() ); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); // Spring推荐的BCrypt加密算法(不可逆) }
}
3.3 认证流程验证
- 访问
http://localhost:8080/swagger-ui.html
,浏览器弹出 Basic 认证弹窗; - 输入
zhangsan/123
(用户名 / 密码),认证通过后加载 Swagger 文档; - 输入错误凭证,返回
401 Unauthorized
(未授权)。
四、多环境管理:@Profile 实现智能控制
通过 Spring 的@Profile
注解,可灵活控制 Swagger 的生命周期:开发 / 测试环境启用文档,生产环境自动禁用。
4.1 开发 / 测试环境(启用 Swagger+Basic 认证)
将 Swagger 配置类标记为@Profile({"dev", "test"})
,仅在指定环境生效:
java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info; @Configuration
@Profile({"dev", "test"}) // 仅在开发/测试环境加载
public class SwaggerConfig { @Bean public OpenAPI customOpenAPI() { return new OpenAPI() .info(new Info() .title("开发环境API文档") .version("1.0.0") .description("仅供开发/测试人员访问")); }
}
4.2 生产环境(彻底禁用 Swagger)
通过配置文件或@Profile
禁用生产环境的 Swagger:
yaml
# application-prod.yml(生产环境)
spring: profiles: prod
springdoc: swagger-ui: enabled: false # 显式禁用Swagger UI(可选,@Profile已生效时可省略) api-docs: enabled: false # 禁用OpenAPI文档接口
五、全链路防护:其他关键方案
5.1 敏感接口隐藏(减少信息泄露)
通过 Swagger 注解隐藏不希望暴露的接口:
java
import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.Operation; @RestController
@RequestMapping("/api/admin")
public class AdminController { // 完全隐藏接口(不展示在文档) @Hidden @PostMapping("/deleteUser") public void deleteUser() { /* 敏感操作(如删除用户) */ } // 细粒度隐藏(保留方法名但不显示) @Operation(hidden = true) @GetMapping("/debug") public void debug() { /* 内部调试接口 */ }
}
5.2 Actuator 端点控制(替代旧版配置)
Spring Boot 3.x 已弃用management.security.enabled
,改为通过以下方式控制:
- 最小化暴露端点(
application-prod.yml
):yaml
management: endpoints: web: exposure: include: "health, info" # 仅暴露健康检查和基本信息 endpoint: health: show-details: never # 不显示详细健康信息(如数据库连接状态)
- 权限限制(Spring Security):
java
.authorizeHttpRequests(auth -> auth .requestMatchers("/actuator/**").hasRole("ADMIN") # 仅ADMIN角色可访问 )
5.3 Nginx 反向代理(外部流量过滤)
通过 Nginx 限制 Swagger 和 Actuator 的外部访问:
nginx
server { listen 80; server_name your-domain.com; # 限制Swagger仅内网访问(如公司办公网192.168.1.0/24) location /swagger-ui/ { allow 192.168.1.0/24; deny all; proxy_pass http://localhost:8080; } # 屏蔽Actuator危险端点(如/shutdown) location = /actuator/shutdown { return 403; # 直接返回403禁止访问 }
}
六、方案对比与最佳实践
方案 | 适用版本 | 安全性 | 维护成本 | 官方推荐 |
---|---|---|---|---|
swagger.basic (旧版) | SpringFox 2.x(<2020) | 低(明文密码) | 高(需自定义) | ❌ |
Spring Security(官方) | Spring Boot 3.x+ | 高(BCrypt 加密) | 低(标准配置) | ✅ |
最佳实践建议:
- 新项目直接采用 Spring Security+SpringDoc 方案,避免旧版
swagger.basic
的安全隐患; - 旧项目迁移时,优先升级至 SpringDoc,并用 Spring Security 替代
swagger.basic
; - 生产环境通过
@Profile
+ 配置文件双重禁用 Swagger,开发环境通过 Basic 认证限制访问。
参考资料