使用 Spring Security 启用 Swagger springdoc-openapi-ui (OpenAPI 3.0) - 无法访问 swagger-ui.html (401)
Posted
技术标签:
【中文标题】使用 Spring Security 启用 Swagger springdoc-openapi-ui (OpenAPI 3.0) - 无法访问 swagger-ui.html (401)【英文标题】:Enabling Swagger springdoc-openapi-ui (OpenAPI 3.0) with Spring Security - Cannot access swagger-ui.html (401) 【发布时间】:2021-06-03 22:41:38 【问题描述】:Swagger OpenAPI 3.0 正在使用 springdoc-openapi-ui 和自定义 OpenAPI Bean。
pom.xml
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-parent</artifactId>
<version>Hoxton.SR10</version>
</parent>
...
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.5.5</version>
</dependency>
Swagger 配置:
spring-security 配置相同的问题
在使用 springdoc-openapi-ui、springdoc-openapi-security 以及 spring-boot-starter-security 和 keycloak-spring-boot-starter 时,我们遇到了一个问题。
pom.xml
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-security</artifactId>
<version>1.5.5</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-spring-boot-starter</artifactId>
<version>12.0.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>2.4.2</version>
</dependency>
DummySecurityConfig(目前使用profile dev):
@Profile("test", "dev")
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
prePostEnabled = true,
securedEnabled = true,
jsr250Enabled = true)
@EnableWebMvc
public class DummySecurityConfig extends WebSecurityConfigurerAdapter implements WebMvcConfigurer
protected static final String[] ACTUATOR_WHITELIST =
"/actuator/**"
;
protected static final String[] SWAGGER_WHITELIST =
"/v3/api-docs/**",
"/swagger-ui/**",
"/swagger-ui.html",
;
@Value("$client.cors.allowed-origins:*")
private String[] allowedOrigins;
@Override
public void configure(HttpSecurity http) throws Exception
http
.authorizeRequests()
.antMatchers("/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic(); //or anything else, e.g. .oauth2ResourceServer().jwt()
@Override
protected void configure(AuthenticationManagerBuilder auth)
auth.authenticationProvider(authenticationProvider());
@Override
public void configure(WebSecurity web)
web.ignoring()
.antMatchers(SWAGGER_WHITELIST)
.antMatchers(ACTUATOR_WHITELIST);
@Override
public void addCorsMappings(CorsRegistry registry)
registry.addMapping("/**")
.allowedOrigins(allowedOrigins);
@Bean
public AuthenticationProvider authenticationProvider()
AuthenticationProvider authenticationProvider = new AuthenticationProvider()
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException
SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_" + authentication.getPrincipal().toString().toUpperCase());
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
authentication.getPrincipal(), authentication.getCredentials(), Collections.singleton(authority));
token.setDetails(authentication);
return token;
@Override
public boolean supports(Class<?> aClass)
return true;
;
return authenticationProvider;
SecurityConfig(示例中未使用,但将来也会使用):
@Profile("staging", "devstaging")
@KeycloakConfiguration
@EnableGlobalMethodSecurity(
prePostEnabled = true,
securedEnabled = true,
jsr250Enabled = true)
@EnableWebMvc
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter implements WebMvcConfigurer
protected static final String[] ACTUATOR_WHITELIST =
"/actuator/**"
;
protected static final String[] SWAGGER_WHITELIST =
"/v3/api-docs/**",
"/swagger-ui/**",
"/swagger-ui.html",
;
@Value("$client.cors.allowed-origins:*")
private String[] allowedOrigins;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
SimpleAuthorityMapper grantedAuthorityMapper = new SimpleAuthorityMapper();
grantedAuthorityMapper.setConvertToUpperCase(true);
grantedAuthorityMapper.setPrefix("ROLE_");
KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(grantedAuthorityMapper);
auth.authenticationProvider(keycloakAuthenticationProvider);
@Bean
public KeycloakSpringBootConfigResolver keycloakConfigResolver()
return new KeycloakSpringBootConfigResolver();
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy()
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
@Override
public void configure(WebSecurity web)
web.ignoring()
.antMatchers(SWAGGER_WHITELIST)
.antMatchers(ACTUATOR_WHITELIST);
@Override
protected void configure(HttpSecurity http) throws Exception
super.configure(http);
http
.csrf().disable()
.cors().and()
.authorizeRequests().anyRequest().authenticated();
@Override
public void addCorsMappings(CorsRegistry registry)
registry.addMapping("/**")
.allowedOrigins(allowedOrigins);
应用程序-dev.yml:
server:
port: 8083
servlet:
context-path: /planning
keycloak:
enabled: false
springdoc:
show-actuator: true
我们已经尝试使用以下链接来解决问题:
Spring security support Allow anonymous access to springdoc-openapi-ui with Spring Security Swagger UI redirecting to /swagger-ui/index.html?configUrl=/v3/api-docs/swagger-config F.A.Q打开 swagger-ui URL 的示例(配置文件开发):
http://localhost:8083/planning/swagger-ui.html(不起作用):
应用代码sn-p:
2021-03-05 09:27:01,530 [http-nio-8083-exec-1] ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [/planning] threw exception [Could not resolve view with name 'redirect:/swagger-ui/index.html?configUrl=/planning/v3/api-docs/swagger-config' in servlet with name 'dispatcherServlet'] with root cause
javax.servlet.ServletException: Could not resolve view with name 'redirect:/swagger-ui/index.html?configUrl=/planning/v3/api-docs/swagger-config' in servlet with name 'dispatcherServlet'
at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1373)
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1138)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1077)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:962)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
http://localhost:8083/planning/swagger-ui/index.html?configUrl=/planning/v3/api-docs/swagger-config(有效但很复杂):
http://localhost:8083/planning/swagger-ui/index.html(手动添加 api-docs "/planning/v3/api-docs" 也可以):
您有什么想法还有什么可能是错误的配置或我们应该改变什么?我们的拉丁文已经结束了。
【问题讨论】:
【参考方案1】:正如日志所说,Could not resolve view with name 'redirect:/swagger-ui/index.html?configUrl=**/planning/v3/api-docs/swagger-config'**
。
在您的网络安全配置中,您只能访问 /v3/api-docs/。
尝试添加/planning/或修改路径。
【讨论】:
感谢@user15400529 的回答和您的提示,但不幸的是它不起作用。 1. 我将 /planning/ 添加到 SWAGGER_WHITELIST 并配置(HttpSecurity http) http.authorizeRequests().antMatchers("/v3/api-docs/**", "/ Planning/", "/swagger-ui/**", "/swagger-ui.html").permitAll(). 仍然出现 401 状态码。 2.我尝试适配springdoc.swagger-ui.configUrl属性,并将值设置为/v3/api-docs/swagger-config。但是,我认为上下文路径(例如 /planning 在我的例子中)已经被用作所有 URL 属性的前缀。 在这两种情况下相同的异常 无法解析名称为“redirect:/swagger-ui/index.html?configUrl=/planning/v3/api-docs/swagger-config”的视图在名称为“dispatcherServlet” 的 servlet 中出现。你知道解决这个问题的任何其他方法/配置吗?以上是关于使用 Spring Security 启用 Swagger springdoc-openapi-ui (OpenAPI 3.0) - 无法访问 swagger-ui.html (401)的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Spring MVC 和 Spring Security 为资源处理程序启用 HTTP 缓存
如何使用 XML 使用 Spring Security Oauth2 启用 /oauth/check_token
如何解决在使用 Spring Boot 和 Spring Security 启用 CSRF 后无法正常工作的登录问题?
使用 Spring Security 启用对 @RestController 的访问