在大部分项目中,都存在权限控制,基本上大部分的接口都需要用户的登录信息。现在主流的采用如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后的接口访问
发表评论