我正在启动我的 springboot web 应用程序并导航到 localhost/api/myservice/swagger-ui/index.html,但收到 401 Unauthorized。从现在起,我已经做了所有常见的事情,有无数的答案,但似乎没有一个专门适用于 spring 和 spring 文档的这对配对。我的一个限制是 Java 1.8,否则我会使用更新版本的软件。手铐。
简短版本: 弹簧启动:2.7.18 弹簧文档:1.8.0
pom.xml 片段:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.18</version>
</parent>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.8.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</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-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
当我检查时,springdocs 的 springboot 的最旧版本已经超过了 Java 1.8。
application.yml 片段:
springdoc:
api-docs:
path: /api-docs/**
swagger-ui:
enabled = true
path = /swagger-ui.html
tryItOutEnabled = false
filter = false
syntaxHighlight.activated = true
spring:
mvc:
pathmatch:
matching-strategy: ant_path_matcher
server:
servlet:
context-path: /api/myservice
SwaggerConfig.java 片段:
@Configuration
public class SwaggerConfig {
@Bean
public GroupedOpenApi api() {
return GroupedOpenApi.builder()
.group("us/cargosphere/**")
.pathsToMatch("/**")
.packagesToExclude("/error.**")
.build();
}
@Bean
public OpenAPI apiInfo() {
final String securitySchemeName = "bearerAuth";
return new OpenAPI()
.addSecurityItem(new SecurityRequirement().addList(securitySchemeName))
.components(new Components().addSecuritySchemes(
securitySchemeName,
new SecurityScheme()
.name(securitySchemeName)
.type(SecurityScheme.Type.HTTP)
.in(SecurityScheme.In.HEADER)
.scheme("bearer")
.bearerFormat("JWT")
))
.info(new Info()
.title(title)
.version(version)
.description("")
)
.servers(Collections.singletonList(
new Server()
.url(contextPath)
.description("Default Server URL")
));
}
}
SpringConfiguration.java 片段:
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SpringConfiguration {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// I have tried very many things here, but I don't see how it could get much more permissive than this ;)
http
.csrf().disable()
.authorizeRequests().anyRequest().permitAll();
return http
.build();
}
@Bean
public RequestMatcher requestMatcher() {
this.log.debug("Creating request matcher");
List<RequestMatcher> requestMatchers = new ArrayList<>();
requestMatchers.add(new AntPathRequestMatcher("/**"));
return new OrRequestMatcher(requestMatchers);
}
@Bean
public CustomAuthenticationFilter customAuthenticationFilter(
RequestMatcher requestMatcher,
AuthenticationConfiguration authenticationConfiguration)
throws Exception {
CustomAuthenticationFilter result = new CustomAuthenticationFilter(requestMatcher);
result.setAuthenticationManager(authenticationConfiguration.getAuthenticationManager());
return result;
}
}
当我取消注释 CustomAuthenticationFilter 内容时,我得到 401 Unauthorized 访问 localhost/api/myservice/swagger-ui/index.html,因为正在应用该类,但是当我将其注释掉时,我就可以正常访问 swagger 页面了。
我是这个版本的 SpringBoot 的新手,也是 Swagger 3 的新手,也是 springdocs 的新手。我在其他使用 FilterRegistrationBean 而不是 CustomAuthenticationFilter 的微服务中使用了此功能,并且我不确定为什么相同的配置在此存储库中不起作用。如果可以在不禁用 csrf 的情况下完成此操作,则可获得奖励积分。
当我导航到 localhost/api/myservice/swagger-ui/index.html 时,我收到 401 Unauthorized。我希望 Swagger 页面无需授权即可加载。
当我注释掉 CustomAuthenticationFilter bean 时,我得到了预期的结果。除了确定 CustomAuthenticationFilter 被用于保护 Swagger 页面(当我不希望这样做时)之外,我不知道为什么。
我也尝试过
@Bean
public WebSecurityCustomizer webSecurityCustomizer(@Value("${server.servlet.context-path}") String contextPath) {
return web -> web
.ignoring()
.antMatchers("/v3/api-docs/**", "/swagger-ui.html", "/swagger-ui/**", contextPath + "/swagger-ui/**");
}
它会在控制台上发出有关使用authorizeHttpRequests 的打印警告。我也尝试过。
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
//.authorizeHttpRequests()
.antMatchers(
"/v2/api-docs",
"/v3/api-docs/**",
"/swagger-resources/**",
"/swagger-ui/**",
"/swagger-ui.html",
"/swagger-ui/index.html",
contextPath + "/swagger-ui/index.html",
"/configuration/ui",
"/configuration/security",
"/webjars/**",
"/api/**",
contextPath + "/swagger-ui/**"
).permitAll()
.and().authorizeRequests().antMatchers("/api/**").authenticated();
return http.build();
}
您要做的第一件事就是从安全上下文(SecurityFilterChain)中排除 swagger 端点,您已经在 WebSecurityCustomizer 中完成了配置,无需再次执行。
你需要的是:
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
return (web) ->
web.ignoring()
.requestMatchers(
new AntPathRequestMatcher("/user/**"),
new AntPathRequestMatcher("/v3/api-docs/**"),
new AntPathRequestMatcher("/swagger-ui/**"),
new AntPathRequestMatcher("/swagger-ui.html")
)
;
}
application.properties(你可以将其更改为yml):
springdoc.api-docs.enabled=true
springdoc.swagger-ui.path=/swagger-ui.html
springdoc.swagger-ui.enabled=true
springdoc.swagger-ui.operationsSorter=method
springdoc.swagger-ui.tryItOutEnabled=true
springdoc.swagger-ui.filter=true
springdoc.swagger-ui.tagsSorter=alpha
springdoc.api-docs.path=/v3/api-docs
最后你可以保持 OpenAPI() 不变,或者:
@OpenAPIDefinition(
info = @Info(
contact = @Contact(
name = ""
),
description = "",
title = "",
version = "",
license = @License(
name = "",
url = ""
),
termsOfService = "Terms of service"
),
servers = {
@Server(
description = "Local ENV",
url = ""
),
@Server(
description = "PROD ENV",
url = ""
),
@Server(
description = "TEST ENV",
url = ""
)
},
security = {
@SecurityRequirement(
name = "bearerAuth"
)
}
)
@SecurityScheme(
name = "bearerAuth",
description = "JWT auth description",
scheme = "bearer",
type = SecuritySchemeType.HTTP,
bearerFormat = "JWT",
in = SecuritySchemeIn.HEADER
)
@Configuration
public class SwaggerConfig {
@Bean
public GroupedOpenApi api() {
return GroupedOpenApi.builder()
.group("us/cargosphere/**")
.pathsToMatch("/**")
.packagesToExclude("/error.**")
.build();
}
}