资讯动态

Spring Boot 2.x + Spring Security + Swagger 2.9.2 完美整合与避坑指南

发布时间:2026/10/13 17:48:12 来源:尧图企业网站定制
1. 这套组合到底解决了什么问题如果你正在维护一个基于 Spring Boot 的后端项目同时用 Spring Security 做认证授权又希望 Swagger 能正常生成接口文档那你大概率遇到过这个场景Swagger UI 页面能打开但所有接口都返回 401 或者 403调试起来非常难受。这不是 Swagger 本身的问题而是 Spring Security 的过滤器链把 Swagger 相关的静态资源和接口请求全部拦截了。我在实际项目里第一次遇到这个问题时花了将近一个下午才彻底理清楚。网上很多方案只给配置代码不解释为什么这样配导致换个版本或者换个项目结构就又失效了。这篇文章我会把整个整合过程拆开讲清楚包括 Spring Security 的拦截机制、Swagger 2.9.2 的资源路径规律、以及如何做到既保证安全又让文档可访问。先明确一下适用场景你有一个 Spring Boot 项目需要对外提供 RESTful 接口接口需要做权限控制同时你希望用 Swagger 自动生成接口文档方便前后端联调。技术栈锁定在 Spring Boot 2.x Spring Security Swagger 2.9.2。如果你用的是 Spring Boot 3.x 或者 SpringDoc OpenAPI思路类似但配置细节不同本文不展开。关键词里提到了“完美整合”和“亲测通过”我理解这意味着配置要能直接跑起来不是理论上的可行。所以我会给出完整的配置类代码并解释每一行的作用。同时我会补充几个实际踩过的坑比如静态资源路径匹配的优先级问题、Security 配置中 antMatchers 的顺序问题、以及 Swagger 2.9.2 在 Spring Boot 2.3 之后的兼容性变化。2. Spring Security 拦截 Swagger 的底层逻辑2.1 过滤器链是怎么把请求拦下来的Spring Security 的核心是一组 Servlet Filter 组成的过滤器链。当一个 HTTP 请求进入应用时会依次经过这些过滤器。其中FilterSecurityInterceptor负责最终的权限判断它会根据配置的SecurityMetadataSource来决定当前请求需要什么权限。如果请求的 URL 没有匹配到任何“放行”规则默认就会被拒绝。Swagger 2.9.2 在 Spring Boot 项目中会注册一批端点主要包括/swagger-ui.htmlSwagger UI 的入口页面/swagger-resources/**Swagger 的资源描述接口/v2/api-docsOpenAPI 规范的 JSON 数据/webjars/**Swagger UI 依赖的前端静态资源/csrf相关如果开启了 CSRF 保护Swagger 的 POST 请求会失败这些路径如果不显式放行Spring Security 就会把它们当作普通受保护资源处理返回 401 或 403。很多人只放行了/swagger-ui.html结果页面能打开但样式丢失、接口列表加载不出来就是因为/webjars/**和/swagger-resources/**没放行。2.2 为什么不能简单粗暴地全部放行有人可能会想那我直接antMatchers(/**).permitAll()不就行了这样做确实能让 Swagger 正常工作但你的业务接口也全部裸奔了这显然不符合安全要求。正确的做法是精确识别 Swagger 相关的路径只对这些路径放行其他接口仍然走认证授权流程。这里有一个关键点Spring Security 的antMatchers匹配是有顺序的。越具体的规则应该放在越前面。如果你先写了antMatchers(/**).authenticated()再写antMatchers(/swagger-ui.html).permitAll()那 Swagger 的放行规则永远不会生效因为所有请求都已经先匹配到了/**这条规则。这个顺序问题是我见过最多的配置错误没有之一。2.3 Swagger 2.9.2 的资源路径清单为了做到精确放行我们需要知道 Swagger 2.9.2 到底会请求哪些路径。根据我实际抓包和源码分析整理如下路径作用是否必须放行/swagger-ui.htmlUI 入口页面是/swagger-resources资源列表是/swagger-resources/**资源详情是/v2/api-docsAPI 文档 JSON是/webjars/**前端静态资源是/csrfCSRF token 接口视情况/favicon.ico网站图标否但建议放行这张表建议直接收藏配置的时候对照着写基本不会漏。3. 从零搭建整合环境的完整步骤3.1 依赖引入的版本匹配问题先看 Maven 依赖。Spring Boot 版本我选用 2.2.x 或 2.3.x这两个版本和 Swagger 2.9.2 配合最稳定。Spring Security 的版本跟随 Spring Boot 父工程即可不需要单独指定。parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version2.3.12.RELEASE/version /parent dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-security/artifactId /dependency dependency groupIdio.springfox/groupId artifactIdspringfox-swagger2/artifactId version2.9.2/version /dependency dependency groupIdio.springfox/groupId artifactIdspringfox-swagger-ui/artifactId version2.9.2/version /dependency /dependencies这里有一个隐藏的坑Spring Boot 2.3 之后默认的路径匹配策略从AntPathMatcher变成了PathPatternParser。Swagger 2.9.2 内部有些地方还在用 Ant 风格的路径匹配这会导致/swagger-resources/**这类通配符匹配失效。解决办法是在application.yml里显式指定spring: mvc: pathmatch: matching-strategy: ant_path_matcher这一行配置非常关键不加的话你会遇到 Swagger 页面 404 或者资源加载失败的问题而且报错信息很不直观容易误以为是 Security 配置错了。3.2 Swagger 配置类的写法Swagger 的配置类本身不复杂但有几个细节需要注意。首先是EnableSwagger2注解不能少其次是Docket的apis和paths要写对否则扫描不到接口。Configuration EnableSwagger2 public class SwaggerConfig { Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage(com.example.demo.controller)) .paths(PathSelectors.any()) .build(); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title(项目接口文档) .description(后端 API 说明) .version(1.0.0) .build(); } }basePackage要改成你自己的 controller 包路径。如果你用了RestController但没写ApiOperation注解接口也会被扫描到只是描述信息为空。建议至少给每个接口加上ApiOperation方便前端同学理解。3.3 Security 配置类的核心代码这是整个整合的关键部分。我直接给出完整的配置类然后逐段解释。Configuration EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() // Swagger 相关路径放行 .antMatchers( /swagger-ui.html, /swagger-resources, /swagger-resources/**, /v2/api-docs, /webjars/**, /favicon.ico ).permitAll() // 其他接口需要认证 .anyRequest().authenticated() .and() .formLogin().permitAll() .and() .httpBasic() .and() .csrf().disable(); } }逐段解释antMatchers(...).permitAll()把 Swagger 相关路径全部放行不需要认证。.anyRequest().authenticated()其他所有请求都需要认证。注意这行必须放在 Swagger 放行规则之后。.formLogin().permitAll()开启表单登录并允许访问登录页面。.httpBasic()开启 HTTP Basic 认证方便用 Postman 等工具调试。.csrf().disable()关闭 CSRF 保护。Swagger 的 POST 请求默认不带 CSRF token不关闭的话会返回 403。生产环境是否关闭 CSRF 需要根据实际情况评估如果关闭建议配合其他安全措施。注意csrf().disable()这一行在开发环境很方便但如果你的项目对外网开放建议评估 CSRF 风险后再决定是否关闭。4. 实测中遇到的五个典型问题与排查过程4.1 Swagger 页面能打开但接口列表为空这个问题的表现是访问/swagger-ui.html能看到 Swagger 的界面框架但接口列表区域是空的浏览器控制台报错Failed to load resource: /v2/api-docs。排查过程先看 Network 面板发现/v2/api-docs请求返回 401。这说明 Security 没有放行这个路径。检查配置类发现只写了/swagger-resources/**漏掉了/v2/api-docs。补上之后问题解决。这个坑的教训是Swagger 的路径不止一个要对照第 2.3 节的表格逐一检查。4.2 静态资源 404 导致页面样式错乱表现是 Swagger 页面能打开但样式全无像纯文本一样。Network 面板显示/webjars/springfox-swagger-ui/...返回 404。排查过程一开始以为是 Security 拦截了但发现返回的是 404 不是 403说明请求已经到达了 Spring MVC 但没找到资源。检查pom.xml发现springfox-swagger-ui依赖引入了但spring-boot-starter-web的版本和 Swagger 2.9.2 不兼容。具体来说Spring Boot 2.3 之后默认的路径匹配策略变化导致 webjars 路径解析失败。解决办法就是第 3.1 节提到的在application.yml里加上spring.mvc.pathmatch.matching-strategy: ant_path_matcher。加上之后样式恢复正常。4.3 antMatchers 顺序写反导致放行失效这个坑我在第 2.2 节提过但实际项目中还是经常有人踩。表现是 Swagger 路径明明写了permitAll()但还是返回 401。排查过程把 Security 配置类的代码打印出来逐行看发现anyRequest().authenticated()写在了antMatchers(/swagger-ui.html).permitAll()前面。Spring Security 的规则匹配是从上到下一旦匹配到就不再往下走。所以所有请求都先匹配到了anyRequest()Swagger 的放行规则形同虚设。解决办法把具体的放行规则全部移到anyRequest()之前。这是一个纯粹的配置顺序问题但很容易被忽略。4.4 Spring Boot 2.3 的兼容性报错表现是启动时报错java.lang.NoClassDefFoundError: org/springframework/web/servlet/config/annotation/PathMatchConfigurer或者类似的类找不到异常。排查过程这个问题的根源是 Spring Boot 2.3 升级了 Spring Framework 版本Swagger 2.9.2 依赖的一些内部 API 发生了变化。除了路径匹配策略的配置外还需要确保springfox-swagger2和springfox-swagger-ui的版本一致都是 2.9.2。如果还是报错可以尝试升级到 Spring Boot 2.3.12.RELEASE 这个版本它和 Swagger 2.9.2 的兼容性最好。我实测过 2.3.0 到 2.3.12 之间的版本2.3.12 最稳定。4.5 生产环境如何安全地关闭 Swagger开发环境用 Swagger 很方便但生产环境通常不希望暴露接口文档。有两种做法第一种是用Profile注解控制 Swagger 配置类只在特定环境下生效Configuration EnableSwagger2 Profile({dev, test}) public class SwaggerConfig { // ... }第二种是在application-prod.yml里通过配置项控制swagger: enabled: false然后在 Swagger 配置类里用ConditionalOnProperty判断。两种方式都可以我个人更推荐第一种因为配置类直接不加载更干净。5. 几个容易被忽略的细节与经验总结5.1 关于 CSRF 的取舍Swagger 的 POST 请求默认不带 CSRF token所以如果开启了 CSRF 保护所有 POST 接口在 Swagger 里测试都会返回 403。关闭 CSRF 是最简单的做法但要注意这会影响整个应用的安全策略。如果你的项目必须开启 CSRF可以考虑给 Swagger 相关的路径单独忽略 CSRFhttp.csrf().ignoringAntMatchers(/swagger-ui.html, /swagger-resources/**, /v2/api-docs);这样既保留了 CSRF 保护又不影响 Swagger 使用。不过要注意ignoringAntMatchers的路径要和放行路径保持一致。5.2 接口文档的注解规范Swagger 2.9.2 支持一套注解来描述接口常用的有Api用在 Controller 类上描述模块ApiOperation用在方法上描述接口功能ApiParam用在参数上描述参数含义ApiModel和ApiModelProperty用在实体类上描述字段这些注解不是必须的但加上之后文档可读性会大幅提升。我建议至少给每个 Controller 加上Api每个接口方法加上ApiOperation。实体类的字段描述也很重要前端同学主要看这部分。5.3 多环境下的 Swagger 路径问题如果你的项目配置了server.servlet.context-path比如/api那 Swagger 的访问路径会变成/api/swagger-ui.html。Security 配置里的antMatchers路径不需要加 context-path因为 Spring Security 匹配的是相对于 context-path 的路径。这一点很容易搞混我见过有人在antMatchers里写了/api/swagger-ui.html结果一直 401。5.4 和拦截器的冲突如果你的项目里还有自定义的HandlerInterceptor要注意拦截器的preHandle方法可能会拦截 Swagger 的请求。解决办法是在拦截器的addInterceptors注册时排除 Swagger 路径registry.addInterceptor(new MyInterceptor()) .addPathPatterns(/**) .excludePathPatterns(/swagger-ui.html, /swagger-resources/**, /v2/api-docs, /webjars/**);这个排除列表和 Security 的放行列表基本一致可以抽成一个常量类统一维护避免两边不一致。5.5 版本升级的注意事项Swagger 2.9.2 是一个比较老的版本官方已经不再维护。如果你的项目允许可以考虑升级到 SpringDoc OpenAPI它对 Spring Boot 2.3 和 Spring Security 的支持更好配置也更简洁。但如果项目已经稳定运行没必要为了升级而升级Swagger 2.9.2 在 Spring Boot 2.x 下完全够用。我在实际项目中的体会是这套组合的稳定性主要取决于三个因素Spring Boot 版本、路径匹配策略配置、Security 规则顺序。把这三点控制好基本不会出问题。另外建议把 Swagger 的放行路径写成一个常量数组在 Security 配置和拦截器配置里共用这样以后加路径只需要改一个地方。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑