Swagger UI不显示控制器端点,因csrf接口请求失败
问题:集成Swagger UI后控制器API未显示,控制台请求
localhost:9000/和localhost:9000/csrf失败 集成Swagger UI后,控制器的API未在界面上显示。查看浏览器开发者控制台,发现localhost:9000/和localhost:9000/csrf接口请求失败,推测问题与CSRF配置相关,但无法确定具体解决方法。
Security配置
@Override protected void configure(AuthenticationManagerBuilder auth) { auth.authenticationProvider(activeDirectoryLdapAuthenticationProvider()); } @Bean public AuthenticationProvider activeDirectoryLdapAuthenticationProvider() { ActiveDirectoryLdapAuthenticationProvider authenticationProvider = new ActiveDirectoryLdapAuthenticationProvider(ldapDomain, ldapUrl,ldapBase); authenticationProvider.setConvertSubErrorCodesToExceptions(true); authenticationProvider.setUseAuthenticationRequestCredentials(true); authenticationProvider.setSearchFilter("(sAMAccountName={1})"); return authenticationProvider; } @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Override protected void configure(HttpSecurity httpSecurity) throws Exception { httpSecurity .csrf() .disable() .exceptionHandling().authenticationEntryPoint(jwtUnAuthorizedResponseAuthenticationEntryPoint).and() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() .authorizeRequests() .antMatchers("/v2/api-docs", "/configuration/ui", "/swagger-resources/**", "/configuration/security", "/swagger-ui.html", "/webjars/**").permitAll() .anyRequest().authenticated(); httpSecurity .addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); httpSecurity .headers() .frameOptions().sameOrigin() //H2 Console Needs this setting .cacheControl(); //disable caching } @Override public void configure(WebSecurity webSecurity) throws Exception { webSecurity .ignoring() .antMatchers( HttpMethod.POST, authenticationPath ) .antMatchers(HttpMethod.OPTIONS, "/**") .and() .ignoring() .antMatchers( HttpMethod.GET, "/" //Other Stuff You want to Ignore ) .and() .ignoring() .antMatchers("/h2-console/**/**");//Should not be in Production! }
Swagger配置
public static final String DEFAULT_INCLUDE_PATTERN = "/deployer/*.*"; @Bean public Docket productApi() { return new Docket(DocumentationType.SWAGGER_2).select() .apis(RequestHandlerSelectors.basePackage("com.org.deployer.controller")) .paths(PathSelectors.regex(DEFAULT_INCLUDE_PATTERN)).build().apiInfo(metaData()) .securityContexts(Lists.newArrayList(securityContext())) .securitySchemes(Lists.newArrayList(apiKey())) .useDefaultResponseMessages(false); } private ApiKey apiKey() { return new ApiKey("JWT", AUTHORIZATION_HEADER, "header"); } private SecurityContext securityContext() { return SecurityContext.builder() .securityReferences(defaultAuth()) .forPaths(PathSelectors.regex(DEFAULT_INCLUDE_PATTERN)) .build(); } List<SecurityReference> defaultAuth() { AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything"); AuthorizationScope[] authorizationScopes = new AuthorizationScope[1]; authorizationScopes[0] = authorizationScope; return Lists.newArrayList( new SecurityReference("JWT", authorizationScopes)); }
/v2/api-docs接口响应
{ "swagger": "2.0", "info": { "description": "deployment Tool ", "version": "1.0", "title": " api", "termsOfService": "Terms of service", "contact": { "name": "Support Team" }, "license": { } }, "host": "localhost:9000", "basePath": "/", "securityDefinitions": { "JWT": { "type": "apiKey", "name": "Authorization", "in": "header" } } }
控制器代码
package com.org.deployer.controller; @RestController @CrossOrigin(origins = "http://localhost:4200") @Api(value = "package operations", description = "Operations pertaining to Package Schedule") public class PackageScheduleController { private static final Logger logger = LoggerFactory.getLogger(PackageScheduleController.class); @Autowired PackageScheduleService packageScheduleService; @PostMapping("/schedule") @ApiOperation(value = "This method is used to get the clients.") public PackageScheduleResponse schedule(@RequestBody PackageScheduleRequest packageScheduleRequest){ try{ logger.info("Schedule Request received for {}",packageScheduleRequest.getName()); System.out.println(packageScheduleRequest.getScheduleTime().toLocalTime()); return packageScheduleService.schedule(packageScheduleRequest); } catch(Exception e){ logger.error("Exception occured",e); throw new RuntimeException("Some Error Occured"); } } @GetMapping("/view-schedule") public List<PackageScheduleDto> schedule(){ try{ logger.info("Request received for fetching upcoming schedule jobs"); return packageScheduleService.fetchAllScheudules(); } catch(Exception e){ logger.error("Exception occured",e); throw new RuntimeException("Some Error Occured"); } } }
解决方案
1. 修正Swagger路径匹配规则
当前Swagger配置的DEFAULT_INCLUDE_PATTERN = "/deployer/*.*"与控制器实际接口路径/schedule、/view-schedule完全不匹配,导致Swagger无法扫描到接口。修改路径匹配规则:
// 匹配控制器的具体接口路径 public static final String DEFAULT_INCLUDE_PATTERN = "/(schedule|view-schedule).*"; // 或宽松匹配所有路径(适合后续扩展接口) public static final String DEFAULT_INCLUDE_PATTERN = "/.*";
2. 处理/csrf请求失败问题
虽然已禁用CSRF,但Swagger UI仍可能尝试获取CSRF令牌,导致请求失败。在HttpSecurity的允许列表中添加/csrf:
.antMatchers("/v2/api-docs", "/configuration/ui", "/swagger-resources/**", "/configuration/security", "/swagger-ui.html", "/webjars/**", "/csrf").permitAll()
3. 验证Swagger扫描范围
确认RequestHandlerSelectors.basePackage("com.org.deployer.controller")的包名与控制器实际包名一致,避免因包名错误导致扫描失败。
4. 确认接口扫描结果
修正配置后,重新访问/v2/api-docs,响应中应包含paths字段,显示控制器的接口信息,此时Swagger UI即可正常展示API。
内容的提问来源于stack exchange,提问作者Manish
相关产品推荐
相关产品推荐

