swagger之接口header控制

在大部分項目中,都存在權限控制,基本上大部分的接口都需要用戶的登錄信息。現在主流的採用如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後的接口訪問

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章