Spring Boot 3 集成 Swagger 踩坑实录:解决 doc.html 404 与 Unauthorized 拦截

Spring Boot 3 集成 Swagger 踩坑实录:解决 doc.html 404 与 Unauthorized 拦截

在 Spring Boot 3 项目中集成 API 接口文档(Swagger / SpringDoc / Knife4j)并配合 Spring Security 使用时,开发者往往会遇到两个非常经典的报错。本文将结合实际排查过程,详细剖析这两个问题的成因及解决方案。

坑位一:访问 doc.html 报 404 异常

1. 案发现场

启动项目后,在浏览器中访问:
http://localhost:9999/doc.html

页面显示 404 白板,后台控制台打印如下异常:

text 复制代码
org.springframework.web.servlet.resource.NoResourceFoundException: No static resource doc.html.

2. 破案分析

这是一个非常典型的"张冠李戴"错误。排查项目的 pom.xml 依赖发现,项目中引入的是 Spring Boot 3 官方标准的 Swagger 方案:SpringDoc OpenAPI:

xml 复制代码
<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
    <version>2.3.0</version>
</dependency>

根据 SpringDoc 官方文档,springdoc-openapi-starter-webmvc-ui 会自动部署 Swagger UI,默认访问地址是:
http://server:port/context-path/swagger-ui.html

doc.html 是 Knife4j(国内常用的增强版 Swagger UI)的专属访问路径。Knife4j 官方也明确说明:Spring Boot 3 只支持 OpenAPI3 规范,推荐使用 knife4j-openapi3-jakarta-spring-boot-starter,访问地址正是 doc.html

既然项目中并没有引入 Knife4j 的依赖,服务器上自然不存在 doc.html 这个静态资源,因此抛出 NoResourceFoundException

3. 解决方案

方案 A:保持现有依赖,使用正确的官方路径

如果你使用的是 SpringDoc 的 starter,那么访问地址应该是:
http://localhost:9999/swagger-ui/index.html

或者通过配置自定义路径:

yaml 复制代码
springdoc:
  swagger-ui:
    path: /swagger-ui.html

配置后访问 /swagger-ui.html 即可。
方案 B:替换依赖,坚持使用 Knife4j

如果你更喜欢 Knife4j 的左侧菜单栏排版,需要修改 pom.xml

  1. 删除或注释掉原有的 springdoc-openapi-starter-webmvc-ui 依赖;
  2. 引入专为 Spring Boot 3 设计的 Knife4j 依赖(注意必须带 jakarta 标识):
xml 复制代码
<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
    <version>4.4.0</version>
</dependency>

Knife4j 的 starter 已经内置了对 springdoc-openapi 的依赖,无需再额外引入 springdoc。刷新 Maven 并重启项目后,即可正常访问:

http://localhost:9999/doc.html

坑位二:访问正确地址却返回 Unauthorized

1. 案发现场

在采用"方案 A",使用正确的地址:
http://localhost:9999/swagger-ui/index.html

访问时,页面没有渲染文档,而是直接返回一段 JSON:

json 复制代码
{"success":false,"errorMsg":"Unauthorized"}

此时后台控制台没有任何报错信息。

2. 破案分析

看到熟悉的 JSON 格式,原因立刻水落石出:请求在到达 Controller 之前,被底层的安全框架拦截了。

查看依赖树可知,项目中引入了 Spring Security 及自定义的安全校验模块。在默认的安全配置下,Spring Security 会拦截所有外部请求,要求携带合法 Token(如 JWT)才能访问。浏览器直接访问文档地址时并没有携带 Token,因此触发鉴权失败,返回自定义的未授权提示。

3. 解决方案:配置 Spring Security 白名单

要解决这个问题,需要为 Swagger 相关的静态资源和接口发放"特别通行证"。

进入项目中的 Spring Security 配置类(通常带有 @Configuration@EnableWebSecurity 注解),在 SecurityFilterChain 的配置中,使用 requestMatchers 将 Swagger 相关的路径设为 permitAll() 放行状态。

针对 Spring Boot 3.x(Spring Security 6.x)的配置参考如下:

java 复制代码
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
        // 省略 csrf、cors 等其他常规配置...
        
        .authorizeHttpRequests(auth -> auth
            // 【核心修复】:将 Swagger/OpenAPI 的相关路径全部加入白名单
            .requestMatchers(
                "/swagger-ui/**",        // 放行 UI 静态页面资源
                "/swagger-ui.html",      // 放行 UI 访问入口
                "/v3/api-docs/**",       // 放行 OpenAPI 的核心数据接口(非常重要,否则页面为空)
                "/swagger-resources/**", // 放行资源配置
                "/webjars/**",           // 放行前端依赖的 webjars
                "/doc.html"              // 兼容放行 knife4j 路径
            ).permitAll()
            
            // 业务接口放行配置示例
            .requestMatchers("/api/user/login", "/api/user/register").permitAll()
            
            // 其余所有请求均需要认证
            .anyRequest().authenticated()
        );
    // 省略自定义的 JWT Filter 等配置...
    
    return http.build();
}

多模块架构注意事项:

如果你的安全配置类写在独立的通用模块(如 common-security)中,修改代码后需要先对该模块执行:
mvn install

然后再重新启动主工程,配置才能真正生效。

重启项目后,再次访问文档地址,完整的接口文档页面即可顺利加载。

小结

  1. 404 问题
    doc.html 是 Knife4j 的专属入口,而 SpringDoc 的默认入口是 /swagger-ui.html/swagger-ui/index.html。根据你引入的依赖选择正确的访问路径,或统一切换为 Knife4j 的 starter。
  2. Unauthorized 问题
    在 Spring Security 6 中,需要通过 SecurityFilterChainauthorizeHttpRequests/swagger-ui/**/v3/api-docs/** 等路径加入白名单,否则文档页面会被安全框架拦截。
    把这两点排查清楚,Spring Boot 3 下集成 Swagger 基本就能一马平川了。
相关推荐
ZC跨境爬虫14 小时前
跟着 MDN 学CSS day_16:(深入掌握背景与边框的艺术)
前端·css·ui·html·tensorflow
武子康14 小时前
Java-07 深入浅出 MyBatis数据库一对多关系模型实战:表结构设计与查询实现
java·后端
花椒技术15 小时前
企业内部 Agent 落地复盘:Gateway、Skill 和二次确认如何串起受控业务执行
后端·agent·ai编程
我是一颗柠檬17 小时前
【MySQL全面教学】MySQL事务与ACID Day9(2026年)
数据库·后端·mysql
枕星而眠17 小时前
数据结构八大排序详解(一):四大简单排序
c语言·数据结构·c++·后端
IT_陈寒17 小时前
React useEffect闭包陷阱差点把我整失业了
前端·人工智能·后端
苍何18 小时前
爆肝两周,我把 Codex 最全实战指南开源了
后端
苏渡苇18 小时前
服务容错的必要性与Spring Cloud Alibaba Sentinel 限流配置实战
spring boot·spring cloud·sentinel
bug菌18 小时前
【SpringBoot 3.x 第254节】夯爆了,数据库访问性能优化实战详解!
数据库·spring boot·后端
Rust研习社18 小时前
从碎片化到标准化:cargo-bp 如何重构 Rust 开发逻辑
后端·rust·编程语言