在大部分項目中,都存在權限控制,基本上大部分的接口都需要用戶的登錄信息。現在主流的採用如jwt或者其他方式,來通過請求時向header加入token,然後服務端解析token。所以我們需要在swagger生成的接口文檔上也要進行header控制,除了接口參數以外,還要輸入token header。
這裏提供swagger header三種方式:
一、在每個controller接口上,標記swagger註解完成(@ApiImplicitParam)
@ApiImplicitParam 指定一個請求參數的配置信息,對接口參數進行配置。他有幾個屬性如下:
name:參數名
value:參數的說明、解釋
required:參數是否必須傳,默認false
paramType:參數放在哪個地方
· header --> 請求頭
· query --> 一般urlcode中的“key=value”,也就是相當於@RequestParam標記的參數
· path --> get請求url中的“/{userId}” ,也就是相當於@PathVariable標記的參數
· body(不常用)
· form(不常用)
dataType:參數類型,默認String,其它值dataType="Integer" 等
defaultValue:參數的默認值
@ApiImplicitParams:用在請求的方法上,包含一組參數說明,用於多個@ApiImplicitParam註解時。
1、header中包含userId值,get接口入參 key,都用@ApiImplicitParam註解表示如下:
@ApiOperation(value = "獲取西工大學校信息", notes = "該接口負責從項目配置中取出西工大的相關信息")
@ApiImplicitParams({
@ApiImplicitParam(paramType = "header", name = "userId", value = "登錄用戶id", dataType = "Integer", required = false),
@ApiImplicitParam(paramType = "query", name = "key", value = "關鍵字", dataType = "Integer", required = true)
})
@GetMapping("/nwpu")
public NwpuVO getNwpuInfo(@RequestParam String key) {
return new NwpuVO(schoolService.getNwpuInfo());
}
2、其中get接口入參key也可以@ApiParam表示(如果沒有接口入參,可以去掉),header還是@ApiImplicitParam註解標記:
@ApiOperation(value = "獲取西工大學校信息", notes = "該接口負責從項目配置中取出西工大的相關信息")
@ApiImplicitParam(paramType = "header", name = "userId", value = "登錄用戶id", dataType = "Integer", required = false)
@GetMapping("/nwpu")
public NwpuVO getNwpuInfo(@ApiParam(name = "key", value = "關鍵字", required = true) @RequestParam String key) {
return new NwpuVO(schoolService.getNwpuInfo());
}
如上方式,效果均如下圖:
二、添加爲全局參數
針對採用swagger配置類的方式配置swagger情況下,可在swagger配置類中進行header控制,因爲大部分的接口都需要token header,所以可以將其作爲全局參數配置每一個在swagger接口上。
ParameterBuilder爲SpringFox項目中的參數構造器,可以用來構造接口參數,一種工廠模型,可直接構造方法初始化屬性,也可分別set。其中部分api說明如下:
和@ApiImplicitParam 的屬性含義基本一致:
name:指定參數名
description:參數的說明、描述解釋
required:參數是否必須傳,默認false
parameterType:參數放在哪個地方
· header --> 請求頭
· query --> 一般urlcode中的“key=value”,也就是相當於@RequestParam標記的參數
· path --> get請求url中的“/{userId}” ,也就是相當於@PathVariable標記的參數
· body(不常用)
· form(不常用)
modelRef:指定參數引用類型,String,Integer等
defaultValue:參數的默認值
代碼如下:
@Configuration
@EnableSwagger2
public class SwaggerConfig {
private String SCAN_BASE_PACKAGE = "cn.code";
private String VERSION = "1.0.0";
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
// 標題
.title("Server API")
// 描述
.description("API文檔")
// 條款地址(公司內部使用無需配置)
.termsOfServiceUrl("")
// 接口(文檔)版本
.version(VERSION)
.build();
}
@Bean
public Docket apiDocket() {
// 全局參數
ParameterBuilder tokenPar = new ParameterBuilder();
List<Parameter> pars = new ArrayList<>();
tokenPar.name("userId").description("token userId").modelRef(new ModelRef("string"))
.parameterType("header").required(true).build();
pars.add(tokenPar.build());
return new Docket(DocumentationType.SWAGGER_2)
.groupName("RestfulApi")
.select()
// 包掃描範圍(對指定的包下進行掃描,如果標註有相關swagger註解,則生成相應文檔)
.apis(RequestHandlerSelectors.basePackage(SCAN_BASE_PACKAGE))
// 過濾掉哪些path不用生成swagger
.paths(PathSelectors.any())
.build()
// 忽略該參數在swagger上的顯示
.ignoredParameterTypes()
.apiInfo(apiInfo())
// 指定全局參數
.globalOperationParameters(pars)
// swagger生效
.enable(true);
}
}
效果如下圖,所有接口上均有該全局參數:
三、無需每個swagger接口上顯示該參數,避免重複輸入參數
上面兩種方式存在一個共同的問題,就是每個swagger接口上均有該參數,每個接口都需要輸入一遍,一種重複性的操作。同時第二種方式,設置全局參數,還存在一個問題,就是這種方式會造成每個swagger接口上均有該參數,但實際項目中可能有些接口是不需要該參數的。拿token header舉例,對於登錄接口就不需要。上面這種方式要解決這個問題的話,需要進行一些額外的操作,很麻煩。所以我們希望,只用在一個地方輸入指定了該參數,需要該參數的接口都不需要在額外輸入了,這樣更方便快捷,並且不需要的地方可以自動過濾。
實現如下:
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.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @Description:swagger配置類
* @Author:
* @Date: 2019-11-18
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig {
private String SCAN_BASE_PACKAGE = "cn.susoncloud";
private String VERSION = "1.0.0";
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
// 標題
.title("Server API")
// 描述
.description("API文檔")
// 條款地址(公司內部使用無需配置)
.termsOfServiceUrl("")
// 接口(文檔)版本
.version(VERSION)
.build();
}
@Bean
public Docket apiDocket() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("RestfulApi")
.select()
// 包掃描範圍(對指定的包下進行掃描,如果標註有相關swagger註解,則生成相應文檔)
.apis(RequestHandlerSelectors.basePackage(SCAN_BASE_PACKAGE))
// 過濾掉哪些path不用生成swagger
.paths(PathSelectors.any())
.build()
// 忽略該參數在swagger上的顯示
.ignoredParameterTypes()
// 配置swagger接口安全校驗規則
.securitySchemes(securitySchemes())
// 配置swagger接口安全校驗上下文中的信息(包含安全權限與安全校驗生效的接口路徑)
.securityContexts(securityContexts())
.apiInfo(apiInfo())
// swagger生效
.enable(true);
}
private List<ApiKey> securitySchemes() {
return new ArrayList<ApiKey>(){{
add(new ApiKey("userId", "userId", "header"));
}};
}
private List<SecurityContext> securityContexts() {
return new ArrayList<SecurityContext>(){{
add(SecurityContext.builder()
.securityReferences(defaultAuth())
.forPaths(PathSelectors.any())
.build());
}};
}
private List<SecurityReference> defaultAuth() {
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
return Arrays.asList(
new SecurityReference("userId", authorizationScopes));
}
}
效果圖如下:在swagger-ui上會顯示一個Authorize按鈕,點開,可以看到需要添加的接口認證參數,也就是上述代碼中指定的header userId。在未添加的情況下,可以看到接口會有紅色感嘆號,添加後,會變成藍色進行提示。這裏注意添加與不添加均可以訪問接口,接口鑑權通不通過就取決於內部接口邏輯了。如果不填Authorize的話,接口就不會傳入 header userId。
填寫Authorize後的接口訪問