Spring Boot集成Swagger遇/v3/api-docs无映射及授权问题求助
问题描述
我开发了一个博客类Spring Boot应用,尝试集成Swagger生成API文档,但访问GET http://localhost:8080/v3/api-docs时,即便使用正确的token仍出现未授权错误,且日志显示该路径无映射。以下是相关配置代码及堆栈日志:
SecurityConfigs类
package com.codewithdurgesh.blog.configs; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.DefaultSecurityFilterChain; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.dao.DaoAuthenticationProvider; import com.codewithdurgesh.blog.sequrity.CustomUserDetailService; import com.codewithdurgesh.blog.sequrity.JWTAuthenticationEntryPoint; import com.codewithdurgesh.blog.sequrity.JwtAuthenticationFilter; @Configuration @EnableMethodSecurity @EnableWebMvc @EnableWebSecurity public class SecurityConfigs { public static final String[] PUBLIC_URLS = { "/v3/api-docs", "/api/v1/auth/**", "/v2/api-docs", "/swagger-resources/**", "/swagger-ui/**", "/webjars/**" }; @Autowired private CustomUserDetailService customUserDetailService; @Autowired private JWTAuthenticationEntryPoint jwtAuthenticationEntryPoint; @Autowired private JwtAuthenticationFilter jwtAutheticationFilter; @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @SuppressWarnings("removal") @Bean public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception { httpSecurity.csrf().disable().authorizeHttpRequests().requestMatchers("/api/v1/auth/**").permitAll() .requestMatchers("/v3/api-docs").permitAll().anyRequest().authenticated().and().exceptionHandling() .authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS); httpSecurity.addFilterBefore(this.jwtAutheticationFilter, UsernamePasswordAuthenticationFilter.class); httpSecurity.authenticationProvider(daoAuthenticationProvider()); DefaultSecurityFilterChain defaultSecurityFilterChain = httpSecurity.build(); return defaultSecurityFilterChain; } @Bean public DaoAuthenticationProvider daoAuthenticationProvider() { DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setUserDetailsService(customUserDetailService); provider.setPasswordEncoder(passwordEncoder()); return provider; } @Bean public AuthenticationManager authenticationManagerBean(AuthenticationConfiguration config) throws Exception { return config.getAuthenticationManager(); } }
Pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.1.5</version> <relativePath /> <!-- lookup parent from repository --> </parent> <groupId>com.codewithdurgesh.blog</groupId> <artifactId>blog-app-api</artifactId> <version>0.0.1-SNAPSHOT</version> <name>blog-app-api</name> <description>this is a backend APIs project for blogging</description> <properties> <java.version>17</java.version> </properties> <dependencies> <dependency> <groupId>jakarta.validation</groupId> <artifactId>jakarta.validation-api</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <!-- 解决javax.xml.bind.DatatypeConverter缺失异常 --> <dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>2.3.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency> <!-- JWT依赖 --> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency> <!-- Swagger UI依赖 --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>3.0.0</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- ModelMapper依赖 --> <dependency> <groupId>org.modelmapper</groupId> <artifactId>modelmapper</artifactId> <version>3.2.0</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> </plugins> </build> </project>
堆栈日志
2023-11-07T00:29:18.915+05:30 DEBUG 10440 --- [nio-8080-exec-6] o.s.security.web.FilterChainProxy : Securing GET /v3/api-docs request token is Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhbmtpdFhZWkB4eXouY29tIiwiZXhwIjoxNjk5MzE1MDQ0LCJpYXQiOjE2OTkyOTcwNDR9.-BvOmOxiFSdhLIoyppvs9xGkwQsDtleDFPhhRB9_SXdcyDThXRw9sKlQcFWyQ6vRfZpirpv7lQ4rwAei6CeyGA Hibernate: select u1_0.id, u1_0.about, u1_0.email, u1_0.user_name, u1_0.password from users u1_0 where u1_0.email=? Hibernate: select r1_0.user, r1_1.id, r1_1.role_name from user_roles r1_0 join role r1_1 on r1_1.id=r1_0.role where r1_0.user=? 2023-11-07T00:29:18.938+05:30 DEBUG 10440 --- [nio-8080-exec-6] o.s.security.web.FilterChainProxy : Secured GET /v3/api-docs 2023-11-07T00:29:18.939+05:30 WARN 10440 --- [nio-8080-exec-6] o.s.web.servlet.PageNotFound : No mapping for GET /v3/api-docs 2023-11-07T00:29:18.940+05:30 DEBUG 10440 --- [nio-8080-exec-6] o.s.security.web.FilterChainProxy : Securing GET /error 2023-11-07T00:29:18.942+05:30 DEBUG 10440 --- [nio-8080-exec-6] o.s.s.w.a.AnonymousAuthenticationFilter : Set SecurityContextHolder to anonymous SecurityContext
解决方案
从日志和配置分析,核心问题有两点:依赖不完整导致Swagger文档接口未生成,以及安全配置未统一放行所有Swagger相关路径。
1. 修复Swagger依赖
你当前仅引入了springfox-swagger-ui,缺少生成OpenAPI文档的核心依赖。由于你使用Spring Boot 3.x,更推荐使用Spring官方维护的SpringDoc(Springfox对Spring Boot 3的支持有限):
替换依赖(推荐SpringDoc)
移除原pom中的Springfox依赖,添加SpringDoc依赖:
<dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> <version>2.2.0</version> </dependency>
若坚持使用Springfox
补充完整的Springfox Boot Starter依赖:
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-boot-starter</artifactId> <version>3.0.0</version> </dependency>
2. 修正安全配置
你已定义PUBLIC_URLS数组,但在securityFilterChain中仅单独放行部分路径,导致其他Swagger相关路径仍被拦截。修改为使用数组统一放行:
@SuppressWarnings("removal") @Bean public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception { httpSecurity.csrf().disable() .authorizeHttpRequests() .requestMatchers(PUBLIC_URLS).permitAll() // 统一使用PUBLIC_URLS数组 .anyRequest().authenticated() .and() .exceptionHandling() .authenticationEntryPoint(jwtAuthenticationEntryPoint) .and() .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS); httpSecurity.addFilterBefore(this.jwtAutheticationFilter, UsernamePasswordAuthenticationFilter.class); httpSecurity.authenticationProvider(daoAuthenticationProvider()); return httpSecurity.build(); }
3. 验证访问路径
- 使用SpringDoc时:
- API文档路径:
http://localhost:8080/v3/api-docs - Swagger UI路径:
http://localhost:8080/swagger-ui.html
- API文档路径:
- 使用Springfox时:
- API文档路径:
http://localhost:8080/v3/api-docs - Swagger UI路径:
http://localhost:8080/swagger-ui/index.html
- API文档路径:
额外检查
- 确保
JwtAuthenticationFilter中对PUBLIC_URLS路径直接放行,不执行token校验逻辑; - 清理Maven缓存并重新构建项目,避免依赖冲突。
内容的提问来源于stack exchange,提问作者Ankit Rege
相关产品推荐
相关产品推荐

