Skip to content

Commit 53c410d

Browse files
author
程序猿DD-翟永超
authored
Merge pull request #69 from SpringForAll/1.7.0
1.7.0
2 parents 7f68606 + 6542bb9 commit 53c410d

File tree

4 files changed

+390
-109
lines changed

4 files changed

+390
-109
lines changed

README.md

Lines changed: 79 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
# 简介
22

3-
[![Build Status](https://travis-ci.org/dyc87112/spring-boot-starter-swagger.svg?branch=1.5.0)](https://travis-ci.org/dyc87112/spring-boot-starter-swagger)
4-
53
该项目主要利用Spring Boot的自动化配置特性来实现快速的将swagger2引入spring boot应用来生成API文档,简化原生使用swagger2的整合代码。
64

75
- 源码地址
@@ -16,19 +14,21 @@
1614
# 版本基础
1715

1816
- Spring Boot:1.5.x
19-
- Swagger:2.7.x
17+
- Swagger:2.8.x
2018

2119
# 如何使用
2220

2321
在该项目的帮助下,我们的Spring Boot可以轻松的引入swagger2,主需要做下面两个步骤:
2422

2523
-`pom.xml`中引入依赖:
2624

25+
> 当前最新版本 1.7.0.RELEASE
26+
2727
```xml
2828
<dependency>
2929
<groupId>com.spring4all</groupId>
3030
<artifactId>swagger-spring-boot-starter</artifactId>
31-
<version>1.6.0.RELEASE</version>
31+
<version>1.7.0.RELEASE</version>
3232
</dependency>
3333
```
3434

@@ -254,8 +254,10 @@ swagger.ui-config.submit-methods=
254254
```properties
255255
# json编辑器
256256
swagger.ui-config.json-editor=false
257+
257258
# 显示请求头
258259
swagger.ui-config.show-request-headers=true
260+
259261
# 页面调试请求的超时时间
260262
swagger.ui-config.request-timeout=5000
261263
```
@@ -276,8 +278,81 @@ swagger.docket.aaa.ignored-parameter-types[1]=com.didispace.demo.Product
276278
> Q. Infinite loop when springfox tries to determine schema for objects with nested/complex constraints?
277279
> A. If you have recursively defined objects, I would try and see if providing an alternate type might work or perhaps even ignoring the offending classes e.g. order using the docket. ignoredParameterTypes(Order.class). This is usually found in Hibernate domain objects that have bidirectional dependencies on other objects.
278280
281+
### Authorization 鉴权配置 (1.7.0 + 支持)
282+
283+
- 新增 Authorization 配置项
284+
285+
```properties
286+
# 鉴权策略ID,对应 SecurityReferences ID
287+
swagger.authorization.name=Authorization
288+
289+
# 鉴权传递的Header参数
290+
swagger.authorization.key-name=token
291+
292+
# 需要开启鉴权URL的正则, 默认^.*$匹配所有URL
293+
swagger.authorization.auth-regex=^.*$
294+
```
295+
296+
备注:目前支持`ApiKey`鉴权模式,后续添加`Oauth2``BasicAuth`支持
297+
298+
**使用须知**
299+
300+
> 1. 默认已经在全局开启了`global`的SecurityReferences,无需配置任何参数就可以使用;
301+
> 2. 全局鉴权的范围在可以通过以上参数`auth-regex`进行正则表达式匹配控制;
302+
> 3. 除了全局开启外,还可以手动通过注解在RestController上进行定义鉴权,使用方式如下:
303+
304+
```java
305+
// 其中的ID Authorization 即为配置项 swagger.authorization.name,详细请关注后面的配置代码
306+
@ApiOperation(value = "Hello World", authorizations = {@Authorization(value = "Authorization")})
307+
@RequestMapping(value = "/hello", method = RequestMethod.GET)
308+
String hello();
309+
```
310+
311+
**关于如何配置实现鉴权,请关注以下code:**
312+
313+
```java
314+
/**
315+
* 配置基于 ApiKey 的鉴权对象
316+
*
317+
* @return
318+
*/
319+
private ApiKey apiKey() {
320+
return new ApiKey(swaggerProperties().getAuthorization().getName(),
321+
swaggerProperties().getAuthorization().getKeyName(),
322+
ApiKeyVehicle.HEADER.getValue());
323+
}
324+
325+
/**
326+
* 配置默认的全局鉴权策略的开关,以及通过正则表达式进行匹配;默认 ^.*$ 匹配所有URL
327+
* 其中 securityReferences 为配置启用的鉴权策略
328+
*
329+
* @return
330+
*/
331+
private SecurityContext securityContext() {
332+
return SecurityContext.builder()
333+
.securityReferences(defaultAuth())
334+
.forPaths(PathSelectors.regex(swaggerProperties().getAuthorization().getAuthRegex()))
335+
.build();
336+
}
337+
338+
/**
339+
* 配置默认的全局鉴权策略;其中返回的 SecurityReference 中,reference 即为ApiKey对象里面的name,保持一致才能开启全局鉴权
340+
*
341+
* @return
342+
*/
343+
private List<SecurityReference> defaultAuth() {
344+
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
345+
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
346+
authorizationScopes[0] = authorizationScope;
347+
return Collections.singletonList(SecurityReference.builder()
348+
.reference(swaggerProperties().getAuthorization().getName())
349+
.scopes(authorizationScopes).build());
350+
}
351+
```
352+
279353
## 贡献者
280354

281355
- [程序猿DD-翟永超](https://github.com/dyc87112/)
282356
- [小火](https://renlulu.github.io/)
283357
- [泥瓦匠BYSocket](https://github.com/JeffLi1993)
358+
- [LarryKoo-古拉里](https://github.com/gumutianqi)

pom.xml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>com.spring4all</groupId>
88
<artifactId>swagger-spring-boot-starter</artifactId>
9-
<version>1.6.0.RELEASE</version>
9+
<version>1.7.0.RELEASE</version>
1010

1111
<name>spring-boot-starter-swagger</name>
1212
<url>https://github.com/SpringForAll/spring-boot-starter-swagger</url>
@@ -48,8 +48,9 @@
4848
<properties>
4949
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
5050
<version.java>1.8</version.java>
51-
<version.swagger>2.7.0</version.swagger>
52-
<version.spring-boot>1.5.6.RELEASE</version.spring-boot>
51+
<version.swagger>2.8.0</version.swagger>
52+
<version.spring-boot>1.5.10.RELEASE</version.spring-boot>
53+
<version.lombok>1.16.18</version.lombok>
5354
</properties>
5455

5556
<dependencies>
@@ -81,7 +82,7 @@
8182
<dependency>
8283
<groupId>org.projectlombok</groupId>
8384
<artifactId>lombok</artifactId>
84-
<version>1.16.12</version>
85+
<version>${version.lombok}</version>
8586
<scope>provided</scope>
8687
</dependency>
8788
<dependency>

src/main/java/com/spring4all/swagger/SwaggerAutoConfiguration.java

Lines changed: 93 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import com.google.common.base.Predicate;
44
import com.google.common.base.Predicates;
5-
import com.google.common.collect.Lists;
65
import org.springframework.beans.BeansException;
76
import org.springframework.beans.factory.BeanFactory;
87
import org.springframework.beans.factory.BeanFactoryAware;
@@ -17,17 +16,19 @@
1716
import org.springframework.web.bind.annotation.RequestMethod;
1817
import springfox.documentation.builders.*;
1918
import springfox.documentation.schema.ModelRef;
20-
import springfox.documentation.service.ApiInfo;
21-
import springfox.documentation.service.Contact;
22-
import springfox.documentation.service.Parameter;
23-
import springfox.documentation.service.ResponseMessage;
19+
import springfox.documentation.service.*;
2420
import springfox.documentation.spi.DocumentationType;
21+
import springfox.documentation.spi.service.contexts.SecurityContext;
2522
import springfox.documentation.spring.web.plugins.Docket;
23+
import springfox.documentation.swagger.web.ApiKeyVehicle;
2624
import springfox.documentation.swagger.web.UiConfiguration;
25+
import springfox.documentation.swagger.web.UiConfigurationBuilder;
2726

2827
import java.util.*;
2928
import java.util.stream.Collectors;
3029

30+
import static com.google.common.collect.Lists.newArrayList;
31+
3132
/**
3233
* @author 翟永超
3334
* Create date:2017/8/7.
@@ -49,15 +50,20 @@ public SwaggerProperties swaggerProperties() {
4950

5051
@Bean
5152
public UiConfiguration uiConfiguration(SwaggerProperties swaggerProperties) {
52-
return new UiConfiguration(
53-
swaggerProperties.getUiConfig().getValidatorUrl(),// url
54-
swaggerProperties.getUiConfig().getDocExpansion(), // docExpansion => none | list
55-
swaggerProperties.getUiConfig().getApiSorter(), // apiSorter => alpha
56-
swaggerProperties.getUiConfig().getDefaultModelRendering(), // defaultModelRendering => schema
57-
swaggerProperties.getUiConfig().getSubmitMethods().split(","),
58-
swaggerProperties.getUiConfig().getJsonEditor(), // enableJsonEditor => true | false
59-
swaggerProperties.getUiConfig().getShowRequestHeaders(), // showRequestHeaders => true | false
60-
swaggerProperties.getUiConfig().getRequestTimeout()); // requestTimeout => in milliseconds, defaults to null (uses jquery xh timeout)
53+
return UiConfigurationBuilder.builder()
54+
.deepLinking(swaggerProperties.getUiConfig().getDeepLinking())
55+
.defaultModelExpandDepth(swaggerProperties.getUiConfig().getDefaultModelExpandDepth())
56+
.defaultModelRendering(swaggerProperties.getUiConfig().getDefaultModelRendering())
57+
.defaultModelsExpandDepth(swaggerProperties.getUiConfig().getDefaultModelsExpandDepth())
58+
.displayOperationId(swaggerProperties.getUiConfig().getDisplayOperationId())
59+
.displayRequestDuration(swaggerProperties.getUiConfig().getDisplayRequestDuration())
60+
.docExpansion(swaggerProperties.getUiConfig().getDocExpansion())
61+
.maxDisplayedTags(swaggerProperties.getUiConfig().getMaxDisplayedTags())
62+
.operationsSorter(swaggerProperties.getUiConfig().getOperationsSorter())
63+
.showExtensions(swaggerProperties.getUiConfig().getShowExtensions())
64+
.tagsSorter(swaggerProperties.getUiConfig().getTagsSorter())
65+
.validatorUrl(swaggerProperties.getUiConfig().getValidatorUrl())
66+
.build();
6167
}
6268

6369
@Bean
@@ -93,14 +99,16 @@ public List<Docket> createRestApi(SwaggerProperties swaggerProperties) {
9399
}
94100

95101
// exclude-path处理
96-
List<Predicate<String>> excludePath = new ArrayList();
102+
List<Predicate<String>> excludePath = new ArrayList<>();
97103
for (String path : swaggerProperties.getExcludePath()) {
98104
excludePath.add(PathSelectors.ant(path));
99105
}
100106

101107
Docket docketForBuilder = new Docket(DocumentationType.SWAGGER_2)
102108
.host(swaggerProperties.getHost())
103109
.apiInfo(apiInfo)
110+
.securitySchemes(Collections.singletonList(apiKey()))
111+
.securityContexts(Collections.singletonList(securityContext()))
104112
.globalOperationParameters(buildGlobalOperationParametersFromSwaggerProperties(
105113
swaggerProperties.getGlobalOperationParameters()));
106114

@@ -118,9 +126,9 @@ public List<Docket> createRestApi(SwaggerProperties swaggerProperties) {
118126
)
119127
).build();
120128

121-
/** ignoredParameterTypes **/
122-
Class[] array = new Class[swaggerProperties.getIgnoredParameterTypes().size()];
123-
Class[] ignoredParameterTypes = swaggerProperties.getIgnoredParameterTypes().toArray(array);
129+
/* ignoredParameterTypes **/
130+
Class<?>[] array = new Class[swaggerProperties.getIgnoredParameterTypes().size()];
131+
Class<?>[] ignoredParameterTypes = swaggerProperties.getIgnoredParameterTypes().toArray(array);
124132
docket.ignoredParameterTypes(ignoredParameterTypes);
125133

126134
configurableBeanFactory.registerSingleton("defaultDocket", docket);
@@ -167,6 +175,8 @@ public List<Docket> createRestApi(SwaggerProperties swaggerProperties) {
167175
Docket docketForBuilder = new Docket(DocumentationType.SWAGGER_2)
168176
.host(swaggerProperties.getHost())
169177
.apiInfo(apiInfo)
178+
.securitySchemes(Collections.singletonList(apiKey()))
179+
.securityContexts(Collections.singletonList(securityContext()))
170180
.globalOperationParameters(assemblyGlobalOperationParameters(swaggerProperties.getGlobalOperationParameters(),
171181
docketInfo.getGlobalOperationParameters()));
172182

@@ -186,9 +196,9 @@ public List<Docket> createRestApi(SwaggerProperties swaggerProperties) {
186196
)
187197
.build();
188198

189-
/** ignoredParameterTypes **/
190-
Class[] array = new Class[docketInfo.getIgnoredParameterTypes().size()];
191-
Class[] ignoredParameterTypes = docketInfo.getIgnoredParameterTypes().toArray(array);
199+
/* ignoredParameterTypes **/
200+
Class<?>[] array = new Class[docketInfo.getIgnoredParameterTypes().size()];
201+
Class<?>[] ignoredParameterTypes = docketInfo.getIgnoredParameterTypes().toArray(array);
192202
docket.ignoredParameterTypes(ignoredParameterTypes);
193203

194204
configurableBeanFactory.registerSingleton(groupName, docket);
@@ -197,6 +207,44 @@ public List<Docket> createRestApi(SwaggerProperties swaggerProperties) {
197207
return docketList;
198208
}
199209

210+
/**
211+
* 配置基于 ApiKey 的鉴权对象
212+
*
213+
* @return
214+
*/
215+
private ApiKey apiKey() {
216+
return new ApiKey(swaggerProperties().getAuthorization().getName(),
217+
swaggerProperties().getAuthorization().getKeyName(),
218+
ApiKeyVehicle.HEADER.getValue());
219+
}
220+
221+
/**
222+
* 配置默认的全局鉴权策略的开关,以及通过正则表达式进行匹配;默认 ^.*$ 匹配所有URL
223+
* 其中 securityReferences 为配置启用的鉴权策略
224+
*
225+
* @return
226+
*/
227+
private SecurityContext securityContext() {
228+
return SecurityContext.builder()
229+
.securityReferences(defaultAuth())
230+
.forPaths(PathSelectors.regex(swaggerProperties().getAuthorization().getAuthRegex()))
231+
.build();
232+
}
233+
234+
/**
235+
* 配置默认的全局鉴权策略;其中返回的 SecurityReference 中,reference 即为ApiKey对象里面的name,保持一致才能开启全局鉴权
236+
*
237+
* @return
238+
*/
239+
private List<SecurityReference> defaultAuth() {
240+
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
241+
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
242+
authorizationScopes[0] = authorizationScope;
243+
return Collections.singletonList(SecurityReference.builder()
244+
.reference(swaggerProperties().getAuthorization().getName())
245+
.scopes(authorizationScopes).build());
246+
}
247+
200248

201249
@Override
202250
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
@@ -206,7 +254,7 @@ public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
206254

207255
private List<Parameter> buildGlobalOperationParametersFromSwaggerProperties(
208256
List<SwaggerProperties.GlobalOperationParameter> globalOperationParameters) {
209-
List<Parameter> parameters = Lists.newArrayList();
257+
List<Parameter> parameters = newArrayList();
210258

211259
if (Objects.isNull(globalOperationParameters)) {
212260
return parameters;
@@ -242,7 +290,7 @@ private List<Parameter> assemblyGlobalOperationParameters(
242290
.map(SwaggerProperties.GlobalOperationParameter::getName)
243291
.collect(Collectors.toSet());
244292

245-
List<SwaggerProperties.GlobalOperationParameter> resultOperationParameters = Lists.newArrayList();
293+
List<SwaggerProperties.GlobalOperationParameter> resultOperationParameters = newArrayList();
246294

247295
if (Objects.nonNull(globalOperationParameters)) {
248296
for (SwaggerProperties.GlobalOperationParameter parameter : globalOperationParameters) {
@@ -259,42 +307,43 @@ private List<Parameter> assemblyGlobalOperationParameters(
259307
/**
260308
* 设置全局响应消息
261309
*
262-
* @param swaggerProperties 支持 POST,GET,PUT,PATCH,DELETE,HEAD,OPTIONS,TRACE
263-
* @param docketForBuilder
310+
* @param swaggerProperties swaggerProperties 支持 POST,GET,PUT,PATCH,DELETE,HEAD,OPTIONS,TRACE
311+
* @param docketForBuilder swagger docket builder
264312
*/
265313
private void buildGlobalResponseMessage(SwaggerProperties swaggerProperties, Docket docketForBuilder) {
266314

267315
SwaggerProperties.GlobalResponseMessage globalResponseMessages =
268316
swaggerProperties.getGlobalResponseMessage();
269317

270-
// POST,GET,PUT,PATCH,DELETE,HEAD,OPTIONS,TRACE 响应消息体
271-
List<ResponseMessage> postResponseMessages = getResponseMessageList(globalResponseMessages.getPost());
272-
List<ResponseMessage> getResponseMessages = getResponseMessageList(globalResponseMessages.getGet());
273-
List<ResponseMessage> putResponseMessages = getResponseMessageList(globalResponseMessages.getPut());
274-
List<ResponseMessage> patchResponseMessages = getResponseMessageList(globalResponseMessages.getPatch());
275-
List<ResponseMessage> deleteResponseMessages = getResponseMessageList(globalResponseMessages.getDelete());
276-
List<ResponseMessage> headResponseMessages = getResponseMessageList(globalResponseMessages.getHead());
277-
List<ResponseMessage> optionsResponseMessages = getResponseMessageList(globalResponseMessages.getOptions());
278-
List<ResponseMessage> trackResponseMessages = getResponseMessageList(globalResponseMessages.getTrace());
318+
/* POST,GET,PUT,PATCH,DELETE,HEAD,OPTIONS,TRACE 响应消息体 **/
319+
List<ResponseMessage> postResponseMessages = getResponseMessageList(globalResponseMessages.getPost());
320+
List<ResponseMessage> getResponseMessages = getResponseMessageList(globalResponseMessages.getGet());
321+
List<ResponseMessage> putResponseMessages = getResponseMessageList(globalResponseMessages.getPut());
322+
List<ResponseMessage> patchResponseMessages = getResponseMessageList(globalResponseMessages.getPatch());
323+
List<ResponseMessage> deleteResponseMessages = getResponseMessageList(globalResponseMessages.getDelete());
324+
List<ResponseMessage> headResponseMessages = getResponseMessageList(globalResponseMessages.getHead());
325+
List<ResponseMessage> optionsResponseMessages = getResponseMessageList(globalResponseMessages.getOptions());
326+
List<ResponseMessage> trackResponseMessages = getResponseMessageList(globalResponseMessages.getTrace());
279327

280328
docketForBuilder.useDefaultResponseMessages(swaggerProperties.getApplyDefaultResponseMessages())
281-
.globalResponseMessage(RequestMethod.POST, postResponseMessages)
282-
.globalResponseMessage(RequestMethod.GET, getResponseMessages)
283-
.globalResponseMessage(RequestMethod.PUT, putResponseMessages)
284-
.globalResponseMessage(RequestMethod.PATCH, patchResponseMessages)
285-
.globalResponseMessage(RequestMethod.DELETE, deleteResponseMessages)
286-
.globalResponseMessage(RequestMethod.HEAD, headResponseMessages)
287-
.globalResponseMessage(RequestMethod.OPTIONS, optionsResponseMessages)
288-
.globalResponseMessage(RequestMethod.TRACE, trackResponseMessages);
329+
.globalResponseMessage(RequestMethod.POST, postResponseMessages)
330+
.globalResponseMessage(RequestMethod.GET, getResponseMessages)
331+
.globalResponseMessage(RequestMethod.PUT, putResponseMessages)
332+
.globalResponseMessage(RequestMethod.PATCH, patchResponseMessages)
333+
.globalResponseMessage(RequestMethod.DELETE, deleteResponseMessages)
334+
.globalResponseMessage(RequestMethod.HEAD, headResponseMessages)
335+
.globalResponseMessage(RequestMethod.OPTIONS, optionsResponseMessages)
336+
.globalResponseMessage(RequestMethod.TRACE, trackResponseMessages);
289337
}
290338

291339
/**
292340
* 获取返回消息体列表
293341
*
294-
* @param globalResponseMessageBodyList
342+
* @param globalResponseMessageBodyList 全局Code消息返回集合
295343
* @return
296344
*/
297-
private List<ResponseMessage> getResponseMessageList(List<SwaggerProperties.GlobalResponseMessageBody> globalResponseMessageBodyList) {
345+
private List<ResponseMessage> getResponseMessageList
346+
(List<SwaggerProperties.GlobalResponseMessageBody> globalResponseMessageBodyList) {
298347
List<ResponseMessage> responseMessages = new ArrayList<>();
299348
for (SwaggerProperties.GlobalResponseMessageBody globalResponseMessageBody : globalResponseMessageBodyList) {
300349
ResponseMessageBuilder responseMessageBuilder = new ResponseMessageBuilder();

0 commit comments

Comments
 (0)