现在的项目基本上都是前后端分离,很多API的调用都需要用到token验证,本文就介绍怎么在swagger的header中自动添加token。
在每个接口上手动添加header
package com.morris.swagger.web;
import com.morris.swagger.vo.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("header")
@Api(tags = "为单个接口添加header")
public class HeaderController {
@GetMapping("token")
@ApiImplicitParams({
@ApiImplicitParam(paramType = "header", name = "token", required = true),
})
@ApiOperation("token")
public R<Void> header() {
return R.ok();
}
}
启动类还是com.morris.swagger.SingleApp。
这种方法的缺点就是需要手动在每个方法上添加@ApiImplicitParam注解来指定header参数,那么有没有一种方式一次性在所有的方法上面加上header参数呢?
全局对每个API都添加header字段
重点是在原先swagger的Docket对象后面添加globalOperationParameters方法。
package com.morris.swagger;
import io.swagger.annotations.ApiOperation;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.schema.ScalarType;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.service.ParameterType;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import static java.util.Collections.singletonList;
@SpringBootApplication(scanBasePackages = "com.morris.swagger.*")
@EnableOpenApi //Enable open api 3.0.3 spec
public class EveryMethodTokenApp {
public static void main(String[] args) {
SpringApplication.run(EveryMethodTokenApp.class, args);
}
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.OAS_30)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.paths(PathSelectors.regex("(?!/error.*).*"))
.build()
.globalRequestParameters(
singletonList(new springfox.documentation.builders.RequestParameterBuilder()
// 不能叫Authorization
.name("token")
.description("token")
.in(ParameterType.HEADER)
.required(true)
.query(q -> q.model(m -> m.scalarModel(ScalarType.STRING)))
.build()));
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Swagger API")
.description("this is a description")
.termsOfServiceUrl("http://springfox.io")
.contact(new Contact("springfox", "https://morris131.github.io", "morris131@163.com"))
.license("Apache License Version 2.0")
.licenseUrl("https://github.com/springfox/springfox/blob/master/LICENSE")
.version("3.0")
.build();
}
}
运行的效果如图:
全站统一header设置
这种方案就简化了第一种方案,在swagger UI上出现一个Authorize按钮,一次输入header参数,全站使用。
package com.morris.swagger;
import io.swagger.annotations.ApiOperation;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpHeaders;
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.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import java.util.Arrays;
import java.util.List;
import static java.util.Collections.singletonList;
/**
* 全局token
*/
@SpringBootApplication(scanBasePackages = "com.morris.swagger.*")
@EnableOpenApi //Enable open api 3.0.3 spec
public class GlobalTokenApp {
public static void main(String[] args) {
SpringApplication.run(GlobalTokenApp.class, args);
}
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.OAS_30)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.paths(PathSelectors.regex("(?!/error.*).*"))
.build()
.securityContexts(Arrays.asList(securityContext()))
// ApiKey的name需与SecurityReference的reference保持一致
.securitySchemes(Arrays.asList(new ApiKey("token", "token", SecurityScheme.In.HEADER.name())));
}
private SecurityContext securityContext() {
return SecurityContext.builder()
.securityReferences(defaultAuth())
//.forPaths(PathSelectors.regex("/*.*"))
.build();
}
private List<SecurityReference> defaultAuth() {
AuthorizationScope authorizationScope
= new AuthorizationScope("global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
return singletonList(
new SecurityReference("token", authorizationScopes));
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Swagger API")
.description("this is a description")
.termsOfServiceUrl("http://springfox.io")
.contact(new Contact("springfox", "https://morris131.github.io", "morris131@163.com"))
.license("Apache License Version 2.0")
.licenseUrl("https://github.com/springfox/springfox/blob/master/LICENSE")
.version("3.0")
.build();
}
}
全局设置完这个参数后,每个方法都会带上header参数。
这种方式好像不传参数也能访问接口,没法做到必填校验。
项目代码
https://gitee.com/morris131/swagger-demo