记录一下SpringBoot下集成Swagger和Swagger的授权相关

前言:之前在有台腾讯云的服务器上部署配置了一个SpringBoot微服务,没过多久平台提示项目下的某些包有安全漏洞,外加上Idea下编写pom依赖时,有些包也是提示了一些安全漏洞,就升级了一下SpringBoot版本和Swagger版本,结果升级版本后Swagger出现了一些问题,这里顺便记录一下Swagger的相关集成和配置

具体代码案例传送门:https://gitea.jnssd.com/jnssd/spring-boot-openapi

1、安装

目前SpringBoot下最新的Swagger版本为3.0版本,其实已经很久没有更新了,貌似现在的最新的SpringBoot上都是集成SpringDoc来配置Swagger的,SpringDoc这里按下不表,Swagger的依赖信息:

1
2
3
4
5
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>

2、Swagger实现

2.1、配置

项目下创建一个SwaggerConfig类文件,添加如下配置信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package com.jnssd.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;

/**
* <h3>spring-boot-openapi</h3>
* <p>配置openapi</p>
*
* @author zxj
* @since 2023-10-13 14:29:58
*/

@Configuration
@EnableOpenApi
public class SwaggerConfig {

@Bean
public Docket api() {
// 常见的SWAGGER_2和OAS_30两种
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
// 扫描特定包
// 扫描所有有注解的api,用这种方式更灵活
// .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
// 扫描所以
//.apis(RequestHandlerSelectors.any())
// 扫描特定包
.apis(RequestHandlerSelectors.basePackage("com.jnssd"))
.paths(PathSelectors.any())
.build();
}

public ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Swagger项目测试")
.description("novel项目接口文档")
.build();
}
}

2.2、访问

浏览器访问

http://127.0.0.1:8080/swagger-ui/index.html

即可得到如下页面信息:

image-20231016144935682

3、Swagger配置安全方案

Swagger在SWAGGER_2模式和OAS_30模式下的安全方案配置是不一样的,以下是通过源码的方式说明和配置

3.1 Swagger下的SWAGGER_2文档

3.1.1、源码说明

我们研究Swagger2下的访问源码,可看见Swagger在如下代码中配置实现了安全规则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 源码具体路径
// springfox-swagger2-3.0.0-sources.jar!\springfox\documentation\swagger2\mappers\SecurityMapper.java
public Map<String, SecuritySchemeDefinition> toSecuritySchemeDefinitions(ResourceListing from) {
if (from == null) {
return new HashMap<>();
}
TreeMap<String, SecuritySchemeDefinition> result
= new TreeMap<>(from.getSecuritySchemes().stream()
.collect(toMap(
SecurityScheme::getName,
toSecuritySchemeDefinition())));
return result;
}

private Function<SecurityScheme, SecuritySchemeDefinition> toSecuritySchemeDefinition() {
return input -> factories.get(input.getType()).create(input);
}

可看见SecuritySchemeDefinition下的安全方案实现的,而该接口由以下几个类实现

image-20231016145724134

而Swagger2下使用oauth2时,是通过OAuth类进行相关配置解析,通过OAuth2AuthFactory类下解析,源码为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 源码具体路径
// springfox-swagger2-3.0.0-sources.jar!\springfox\documentation\swagger2\mappers\OAuth2AuthFactory.java
public SecuritySchemeDefinition create(SecurityScheme input) {
OAuth oAuth = (OAuth) input;
OAuth2Definition definition = new OAuth2Definition();
for (GrantType each : oAuth.getGrantTypes()) {
if ("authorization_code".equals(each.getType())) {
definition.accessCode(((AuthorizationCodeGrant) each).getTokenRequestEndpoint().getUrl(),
((AuthorizationCodeGrant) each).getTokenEndpoint().getUrl());
} else if ("implicit".equals(each.getType())) {
definition.implicit(((ImplicitGrant) each).getLoginEndpoint().getUrl());
} else if ("application".equals(each.getType())) {
// NOTE: swagger 1 doesn't support this
definition.application(((ClientCredentialsGrant) each).getTokenUrl());
} else if ("password".equals(each.getType())) {
// NOTE: swagger 1 doesn't support this
definition.password(((ResourceOwnerPasswordCredentialsGrant) each).getTokenUrl());
} else {
throw new IllegalArgumentException(String.format("Security scheme of type %s not supported",
input.getClass().getSimpleName()));
}
}
for (AuthorizationScope each : oAuth.getScopes()) {
definition.addScope(each.getScope(), each.getDescription());
}
VendorExtensionsMapper vendorMapper = new VendorExtensionsMapper();
definition.setVendorExtensions(vendorMapper.mapExtensions(input.getVendorExtensions()));
return definition;
}

3.1.2、具体实现

SwaggerConfig类具体配置如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package com.jnssd.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.AntPathMatcher;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.OAuthBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger.web.ApiKeyVehicle;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
* <h3>spring-boot-openapi</h3>
* <p></p>
*
* @author zxj
* @since 2023-10-12 17:13:09
*/
@Configuration
@EnableSwagger2
@EnableOpenApi
public class SwaggerConfig {

private final String[] securitySchemeNames = {"ApiKey模式", "basicAuth模式", "oauth2的Password模式", "oauth2的authorization_code模式", "oauth2的implicit模式", "oauth2的clientCredentials模式"};


@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo()).select()
// 扫描特定包
// 扫描所有有注解的api,用这种方式更灵活
// .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
//.apis(RequestHandlerSelectors.any())
.apis(RequestHandlerSelectors.basePackage("com.jnssd"))
.paths(PathSelectors.any())
.build()
.securitySchemes(initSecuritySchemeList())
.securityContexts(Collections.singletonList(securityContext()));
}

public ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Swagger项目测试")
.description("novel项目接口文档")
.build();
}


/**
* 初始化安全方案
*
* @return
*/
public List<SecurityScheme> initSecuritySchemeList() {
List<SecurityScheme> list = new ArrayList<>();
list.add(securitySchemeBasicAuth());
list.add(securitySchemeApiKey());

// oauth2下的几个模式配置
// 1. 密码模式
list.add(securitySchemeOAuth2Password());
// 2. 客户端模式
list.add(securitySchemeOAuth2ClientCredentials());
// 3. 授权码模式
list.add(securitySchemeOAuth2AuthorizationCode());
// 4. 简化模式
list.add(securitySchemeOAuth2Implicit());
return list;
}

// ApiKey模式
private SecurityScheme securitySchemeApiKey() {
return new ApiKey("ApiKey模式", "Authorization", ApiKeyVehicle.HEADER.getValue());
}

// basicAuth模式
private SecurityScheme securitySchemeBasicAuth() {
return new BasicAuth("basicAuth模式");
}

// oauth2下面的password模式
private SecurityScheme securitySchemeOAuth2Password() {
List<GrantType> grantTypes = new ArrayList<>();
grantTypes.add(new ResourceOwnerPasswordCredentialsGrant("/oauth/token"));
return new OAuthBuilder().name("oauth2的Password模式").scopes(scopes()).grantTypes(grantTypes).build();
}

// oauth2下面的authorization_code模式
private SecurityScheme securitySchemeOAuth2AuthorizationCode() {
List<GrantType> grantTypes = new ArrayList<>();
TokenRequestEndpoint tokenRequestEndpoint = new TokenRequestEndpoint("/oauth/authorize", "", "");
TokenEndpoint tokenEndpoint = new TokenEndpoint("/oauth/token", "token");
grantTypes.add(new AuthorizationCodeGrant(tokenRequestEndpoint, tokenEndpoint));
return new OAuthBuilder().name("oauth2的authorization_code模式").scopes(scopes()).grantTypes(grantTypes).build();
}

// oauth2下面的implicit模式
private SecurityScheme securitySchemeOAuth2Implicit() {
List<GrantType> grantTypes = new ArrayList<>();
ImplicitGrant implicitGrant = new ImplicitGrant(new LoginEndpoint("/oauth/authorize"), "token");
grantTypes.add(implicitGrant);
return new OAuthBuilder().name("oauth2的implicit模式").scopes(scopes()).grantTypes(grantTypes).build();
}

// oauth2下面的ClientCredentials模式
private SecurityScheme securitySchemeOAuth2ClientCredentials() {
List<GrantType> grantTypes = new ArrayList<>();
grantTypes.add(new ClientCredentialsGrant("/oauth/token"));
return new OAuthBuilder().name("oauth2的clientCredentials模式").scopes(scopes()).grantTypes(grantTypes).build();
}

/**
* oauth2访问范围
*
* @return
*/
private List<AuthorizationScope> scopes() {
List<AuthorizationScope> list = new ArrayList<>();
list.add(new AuthorizationScope("read_scope", "Grants read access"));
list.add(new AuthorizationScope("write_scope", "Grants write access"));
list.add(new AuthorizationScope("admin_scope", "Grants read write and delete access"));
return list;
}

/**
* 配置接口下哪些需要实现安全访问
* @return
*/
private SecurityContext securityContext() {
List<SecurityReference> list = new ArrayList<>();
// 这里的SecurityReference第一个参数值必须和SecurityScheme的name值一致
Arrays.stream(securitySchemeNames).forEach(name -> list.add(new SecurityReference(name, new AuthorizationScope[0])));
return SecurityContext.builder().operationSelector(operationContext -> {
System.out.println("operationContext" + operationContext);
// 除了get方法其他方法都要校验
// return !operationContext.httpMethod().name().equals("GET");

// 通过地址模糊匹配
AntPathMatcher pathMatcher = new AntPathMatcher();
String path = operationContext.requestMappingPattern();
return pathMatcher.match("/menu/**", path) || pathMatcher.match("/user/**", path);
}).securityReferences(list).build();
}

}

3.1.3、相关安全方案配置后的页面如下:

  • ApiKey模式

    1
    2
    3
    4
    // ApiKey模式
    private SecurityScheme securitySchemeApiKey() {
    return new ApiKey("ApiKey模式", "Authorization", ApiKeyVehicle.HEADER.getValue());
    }

    image-20231016154055710

  • basicAuth模式

    1
    2
    3
    4
    // basicAuth模式
    private SecurityScheme securitySchemeBasicAuth() {
    return new BasicAuth("basicAuth模式");
    }

    image-20231016154140203

  • oauth2下面的password模式

    1
    2
    3
    4
    5
    6
    // oauth2下面的password模式
    private SecurityScheme securitySchemeOAuth2Password() {
    List<GrantType> grantTypes = new ArrayList<>();
    grantTypes.add(new ResourceOwnerPasswordCredentialsGrant("/oauth/token"));
    return new OAuthBuilder().name("oauth2的Password模式").scopes(scopes()).grantTypes(grantTypes).build();
    }

    image-20231016154240617

  • oauth2下面的authorization_code模式

    1
    2
    3
    4
    5
    6
    7
    8
    // oauth2下面的authorization_code模式
    private SecurityScheme securitySchemeOAuth2AuthorizationCode() {
    List<GrantType> grantTypes = new ArrayList<>();
    TokenRequestEndpoint tokenRequestEndpoint = new TokenRequestEndpoint("/oauth/authorize", "", "");
    TokenEndpoint tokenEndpoint = new TokenEndpoint("/oauth/token", "token");
    grantTypes.add(new AuthorizationCodeGrant(tokenRequestEndpoint, tokenEndpoint));
    return new OAuthBuilder().name("oauth2的authorization_code模式").scopes(scopes()).grantTypes(grantTypes).build();
    }

    image-20231016154418633

  • oauth2下面的implicit模式

    1
    2
    3
    4
    5
    6
    7
    // oauth2下面的implicit模式
    private SecurityScheme securitySchemeOAuth2Implicit() {
    List<GrantType> grantTypes = new ArrayList<>();
    ImplicitGrant implicitGrant = new ImplicitGrant(new LoginEndpoint("/oauth/authorize"), "token");
    grantTypes.add(implicitGrant);
    return new OAuthBuilder().name("oauth2的implicit模式").scopes(scopes()).grantTypes(grantTypes).build();
    }

    image-20231016154502791

  • oauth2下面的ClientCredentials模式

    1
    2
    3
    4
    5
    6
    // oauth2下面的ClientCredentials模式
    private SecurityScheme securitySchemeOAuth2ClientCredentials() {
    List<GrantType> grantTypes = new ArrayList<>();
    grantTypes.add(new ClientCredentialsGrant("/oauth/token"));
    return new OAuthBuilder().name("oauth2的clientCredentials模式").scopes(scopes()).grantTypes(grantTypes).build();
    }

    image-20231016154334683

3.2 Swagger下的OAS_30文档

3.2.1、源码说明

如果在创建Docket时使用的是 new Docket(DocumentationType.OAS_30)构建,页面上只有ApiKey模式和BasicAuth模式,OAS_30文档下的安全方案的创建必须是通过OAuth2Scheme类来构建的,因为在服务上渲染构建Swagger页面时,是通过如下配置生成的,具体代码如下:

springfox-oas-3.0.0-sources.jar!\springfox\documentation\oas\mappers\SecuritySchemeMapper.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
void mapScheme(Map<String, SecurityScheme> map, springfox.documentation.service.SecurityScheme scheme) {
SecurityScheme mapped = null;
SecurityScheme securityScheme = new SecurityScheme()
.extensions(new VendorExtensionsMapper().mapExtensions(scheme.getVendorExtensions()));
if (scheme instanceof HttpAuthenticationScheme) {
mapped = securityScheme
.type(SecurityScheme.Type.HTTP)
.description(scheme.getDescription())
.bearerFormat(((HttpAuthenticationScheme) scheme).getBearerFormat())
.scheme(((HttpAuthenticationScheme) scheme).getScheme());
} else if (scheme instanceof OAuth2Scheme) {
OAuthFlows flows = new OAuthFlows();
Scopes scopes = new Scopes();
((OAuth2Scheme) scheme).getScopes()
.forEach(s -> scopes.addString(s.getScope(), s.getDescription()));
OAuthFlow flow = new OAuthFlow()
.authorizationUrl(((OAuth2Scheme) scheme).getAuthorizationUrl())
.refreshUrl(((OAuth2Scheme) scheme).getRefreshUrl())
.tokenUrl(((OAuth2Scheme) scheme).getTokenUrl())
.scopes(scopes);
switch (((OAuth2Scheme) scheme).getFlowType()) {
case "password":
flows.password(flow);
break;
case "clientCredentials":
flows.clientCredentials(flow);
break;
case "authorizationCode":
flows.authorizationCode(flow);
break;
case "implicit":
default:
flows.implicit(flow);
break;
}
mapped = securityScheme
.type(SecurityScheme.Type.OAUTH2)
.description(scheme.getDescription())
.flows(flows);
} else if (scheme instanceof ApiKey) {
mapped = securityScheme
.type(SecurityScheme.Type.APIKEY)
.name(scheme.getName())
.in(mapIn(((ApiKey) scheme).getPassAs()));
} else if (scheme instanceof OpenIdConnectScheme) {
mapped = securityScheme
.type(SecurityScheme.Type.OPENIDCONNECT)
.name(scheme.getName())
.openIdConnectUrl(((OpenIdConnectScheme) scheme).getOpenIdConnectUrl());
}
if (mapped != null) {
map.put(scheme.getName(), mapped);
}
}

因此,如果配置的权限的文档是OAS_30的,需要通过OAuth2Scheme对象构建相关安全规则

3.2.2、具体配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
package com.jnssd.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.AntPathMatcher;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.OpenIdConnectSchemeBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
* <h3>spring-boot-openapi</h3>
* <p>配置openapi</p>
*
* @author zxj
* @since 2023-10-13 14:29:58
*/

@Configuration
@EnableOpenApi
public class SwaggerConfig {

private final String[] securitySchemeNames = {"JWT模式", "ApiKey模式", "OIDC模式", "oauth2的Password模式", "oauth2的authorization_code模式", "oauth2的implicit模式", "oauth2的clientCredentials模式"};

@Bean
public Docket api() {
return new Docket(DocumentationType.OAS_30)
.apiInfo(apiInfo())
.select()
// 扫描特定包
// 扫描所有有注解的api,用这种方式更灵活
// .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
//.apis(RequestHandlerSelectors.any())
.apis(RequestHandlerSelectors.basePackage("com.jnssd"))
.paths(PathSelectors.any())
.build()
.securitySchemes(initSecuritySchemeList())
.securityContexts(Collections.singletonList(securityContext()));
}

public ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Swagger项目测试")
.description("novel项目接口文档")
.build();
}

private List<SecurityScheme> initSecuritySchemeList() {

List<SecurityScheme> list = new ArrayList<>();
list.add(httpAuthenticationScheme());
list.add(securitySchemeApiKey());
list.add(securitySchemeOpenIdConnect());

// 配置oauth2的几种模式
list.add(securitySchemeOauth2ClientCredentials());
list.add(securitySchemeOauth2implicit());
list.add(securitySchemeOauth2Password());
list.add(securitySchemeOauth2AuthorizationCode());
return list;
}

// basic模式或者JWT模式
private SecurityScheme httpAuthenticationScheme() {
// 之前的basic模式
// return HttpAuthenticationScheme.BASIC_AUTH_BUILDER.name("basic模式").build();
return HttpAuthenticationScheme.JWT_BEARER_BUILDER.name("JWT模式").build();
}

// ApiKey模式
private SecurityScheme securitySchemeApiKey() {
return new ApiKey("ApiKey模式", "Authorization", "header");
}

// OpenIdConnect

// return new OpenIdConnectSchemeBuilder()
// .name("OpenId授权")
// .description("OpenIdConnect授权配置")
// .openIdConnectUrl("https://your-openid-connect-url")
// .build();
private SecurityScheme securitySchemeOpenIdConnect() {
// Swagger配置 OpenIdConnect
return new OpenIdConnectSchemeBuilder()
.name("OpenIdConnect授权")
.description("OpenIdConnect授权配置")
.openIdConnectUrl("https://your-openid-connect-url")
.build();
}

// oauth2下面的authorization_code模式
private SecurityScheme securitySchemeOauth2AuthorizationCode() {
return OAuth2Scheme.OAUTH2_AUTHORIZATION_CODE_FLOW_BUILDER
.name("oauth2的authorization_code模式")
.authorizationUrl("/oauth/authorize")
.tokenUrl("/oauth/token")
.scopes(scopes())
.build();
}

// oauth2下面的implicit模式
private SecurityScheme securitySchemeOauth2implicit() {
return OAuth2Scheme.OAUTH2_IMPLICIT_FLOW_BUILDER
.name("oauth2的implicit模式")
.authorizationUrl("/oauth/authorize")
.scopes(scopes())
.build();
}

// oauth2下面的ClientCredentials模式
private SecurityScheme securitySchemeOauth2ClientCredentials() {
return OAuth2Scheme.OAUTH2_CLIENT_CREDENTIALS_FLOW_BUILDER
.name("oauth2的clientCredentials模式")
.tokenUrl("/oauth/authorize")
.scopes(scopes())
.build();
}

// oauth2下面的password模式
private SecurityScheme securitySchemeOauth2Password() {
return OAuth2Scheme.OAUTH2_PASSWORD_FLOW_BUILDER
.name("oauth2的Password模式")
.tokenUrl("/oauth/token")
.scopes(scopes())
.build();
}


private List<AuthorizationScope> scopes() {
List<AuthorizationScope> list = new ArrayList<>();
list.add(new AuthorizationScope("read_scope", "Grants read access"));
list.add(new AuthorizationScope("write_scope", "Grants write access"));
list.add(new AuthorizationScope("admin_scope", "Grants read write and delete access"));
return list;
}

private SecurityContext securityContext() {
List<SecurityReference> list = new ArrayList<>();
// 这里的SecurityReference第一个参数值必须和SecurityScheme的name值一致
Arrays.stream(securitySchemeNames).forEach(name -> list.add(new SecurityReference(name, new AuthorizationScope[0])));
return SecurityContext.builder().operationSelector(operationContext -> {
System.out.println("operationContext" + operationContext);
// 除了get方法其他方法都要校验
// return !operationContext.httpMethod().name().equals("GET");

// 通过地址模糊匹配
AntPathMatcher pathMatcher = new AntPathMatcher();
String path = operationContext.requestMappingPattern();
return pathMatcher.match("/menu/**", path) || pathMatcher.match("/user/**", path);
}).securityReferences(list).build();
}
}

3.2.3、相关安全方案配置后的页面如下:

OAS_30的文档下在basicAuth模式基础下,添加了JWT模式,使用HttpAuthenticationScheme类来构建basic模式和JWT模式,而其他方案的显示差不多之前展示了就不展示了,这里只对JWT模式说明

  • JWT模式

    image-20231016161915583

4、问题

4.1、启动报错如:Failed to start bean ‘documentationPluginsBootstrapper’

如果使用的是2.7以上的SpringBoot版本,启动后会报如下错误信息:

1
2
3
4
5
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2023-10-16 14:28:47.623 ERROR 1476 --- [ main] o.s.boot.SpringApplication : Application run failed

org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:182) ~[spring-context-5.3.30.jar:5.3.30]

需要在application.yml下添加如下配置:

1
2
3
4
spring:
mvc:
pathmatch:
matching-strategy: ant_path_matcher

重新启动即可