Spring Boot中用SecurityFilterChain集成Swagger UI遇未授权错误
解决Spring Boot中SecurityFilterChain与Swagger UI的未授权问题
你的问题核心是SecurityFilterChain未放行Springfox 3.0所需的全部Swagger相关端点,加上配置中的重复CORS设置等细节问题,导致验证拦截了Swagger资源。以下是具体修正方案:
一、修改SecurityConfig,补充完整Swagger放行路径
Springfox 3.0除了你已配置的路径,还需要放行/v2/api-docs、/v3/api-docs、/webjars/**这些端点(Swagger UI依赖这些接口加载文档数据),同时合并重复的CORS配置避免冲突:
@EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class WebSecurityConfig { @Autowired UserDetailsServiceImpl userDetailsService; @Autowired private AuthEntryPointJwt unauthorizedHandler; @Bean public AuthTokenFilter authenticationJwtTokenFilter() { return new AuthTokenFilter(); } @Bean public DaoAuthenticationProvider authenticationProvider() { DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider(); authProvider.setUserDetailsService(userDetailsService); authProvider.setPasswordEncoder(passwordEncoder()); return authProvider; } @Bean public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception { return authConfig.getAuthenticationManager(); } @Bean public PasswordEncoder passwordEncoder() { return NoOpPasswordEncoder.getInstance(); // return new BCryptPasswordEncoder(); } @Bean @Order(1) // 确保此过滤器链优先执行 public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .cors(cors -> cors.configurationSource(request -> { CorsConfiguration config = new CorsConfiguration(); config.setAllowedHeaders(Collections.singletonList("*")); config.setAllowedMethods(Collections.singletonList("*")); config.addAllowedOrigin("*"); config.setAllowCredentials(true); return config; })) .csrf(csrf -> csrf.disable()) .exceptionHandling(ex -> ex.authenticationEntryPoint(unauthorizedHandler)) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .authorizeRequests(auth -> auth // 放行所有Swagger相关端点 .antMatchers("/swagger-ui/**", "/swagger-resources/**", "/swagger-ui.html", "/v2/api-docs", "/v3/api-docs", "/webjars/**") .permitAll() .anyRequest().authenticated()); http.authenticationProvider(authenticationProvider()); http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class); return http.build(); } }
二、优化SwaggerConfig(适配Springfox 3.0的OpenAPI 3规范)
Springfox 3.0默认支持OpenAPI 3,建议将DocumentationType.SWAGGER_2改为DocumentationType.OAS_30提升兼容性:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.oas.annotations.EnableOpenApi; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.ApiKey; import springfox.documentation.service.AuthorizationScope; import springfox.documentation.service.Contact; import springfox.documentation.service.SecurityReference; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spi.service.contexts.SecurityContext; import springfox.documentation.spring.web.plugins.Docket; import java.util.Arrays; import java.util.Collections; import java.util.List; @Configuration @EnableOpenApi // 启用OpenAPI支持 public class SwaggerConfig { public static final String AUTHORIZATION_HEADER = "Authorization"; private ApiKey apiKey() { return new ApiKey("JWT", AUTHORIZATION_HEADER, "header"); } private ApiInfo apiInfo() { return new ApiInfo("Spring Boot API", "Spring Boot API 文档", "1.0", "Terms of service", new Contact("Test", "www.xyz.com", "test@gmail.com"), "License of API", "API license URL", Collections.emptyList()); } @Bean public Docket api() { return new Docket(DocumentationType.OAS_30) // 改用OpenAPI 3规范 .apiInfo(apiInfo()) .securityContexts(Arrays.asList(securityContext())) .securitySchemes(Arrays.asList(apiKey())) .select() .apis(RequestHandlerSelectors.any()) .paths(PathSelectors.any()) .build(); } private SecurityContext securityContext() { return SecurityContext.builder().securityReferences(defaultAuth()).build(); } private List<SecurityReference> defaultAuth() { AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything"); AuthorizationScope[] authorizationScopes = new AuthorizationScope[1]; authorizationScopes[0] = authorizationScope; return Arrays.asList(new SecurityReference("JWT", authorizationScopes)); } }
三、额外注意事项
- 检查
AuthTokenFilter的路径匹配逻辑,确保不会误拦截已放行的Swagger端点。 - 若使用Spring Boot 2.7+,需在
application.properties中添加以下配置,兼容Springfox的路径匹配:spring.mvc.pathmatch.matching-strategy=ant_path_matcher
内容的提问来源于stack exchange,提问作者Amol Gharpure
相关产品推荐
相关产品推荐

