Spring Boot Swagger 安全防护全解析:从旧版实践到官方规范

发布于:2025-05-14 ⋅ 阅读:(22) ⋅ 点赞:(0)

摘要

本文系统梳理 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 认证流程验证
  1. 访问http://localhost:8080/swagger-ui.html,浏览器弹出 Basic 认证弹窗;
  2. 输入zhangsan/123(用户名 / 密码),认证通过后加载 Swagger 文档;
  3. 输入错误凭证,返回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 认证限制访问。

参考资料

  1. Spring Security 官方文档
  2. SpringDoc OpenAPI 指南
  3. Spring Boot Actuator 安全配置

网站公告

今日签到

点亮在社区的每一天
去签到