xiaoymin / knife4j

Knife4j is a set of Swagger2 and OpenAPI3 All-in-one enhancement solution
https://doc.xiaominfo.com
Apache License 2.0
4.15k stars 622 forks source link

knife4j-openapi3 安全认证不生效 #653

Closed Li-Stone closed 7 months ago

Li-Stone commented 1 year ago

knife4j-openapi3 安全认证不生效

<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-openapi3-spring-boot-starter</artifactId>
    <version>4.3.0</version>
</dependency>
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.15</version>
    <relativePath/>
</parent>
@Configuration
public class SwaggerConfig {
    @Bean
    public OpenAPI openApi() {
        return new OpenAPI()
                .info(new Info().title("demo ").version("1.0").description("demo"))
                .addSecurityItem(new SecurityRequirement().addList(HttpHeaders.AUTHORIZATION))
                .components(new Components().addSecuritySchemes(HttpHeaders.AUTHORIZATION,
                        new SecurityScheme().name(HttpHeaders.AUTHORIZATION).type(SecurityScheme.Type.HTTP).scheme("bearer"))
                );
    }
}

问题说明

  1. 访问原生swagger-ui.html 接口请求可以自动带上header
  2. 访问knife4j 的 doc.html 接口请求则不能自动带上header
  3. 在controller上加上@SecurityRequirement(name = HttpHeaders.AUTHORIZATION) 后在knife4j的doc.html 里是可以正常在请求时带上header的,但是为什么不手动加这个注解就不行呢。
xiaoymin commented 11 months ago

在使用OpenAPI实体类中添加components中的Security方案是定义,需要在接口中指定使用那个security方案

在使用@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)注解后我认为是该接口的方案使用,这个和之前在定义OpenAPI2规范的securiyt时,指定哪些path来使用我觉得是一样的,这种我觉得是合理的啊?

最终的OpenAPI3规范结构会被解析(示例):

{
    "paths": {
        "/test/description": {
            "post": {
                "tags": [
                    "测试模块"
                ],
                "summary": "描述1",
                "operationId": "description",
                "parameters": [
                    {
                        "name": "sortType",
                        "in": "query",
                        "description": "描述",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "description": "描述"
                        }
                    },
                    {
                        "name": "pageNo",
                        "in": "query",
                        "description": "页码",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "description": "页码",
                            "example": 1
                        },
                        "example": 1
                    },
                    {
                        "name": "pageSize",
                        "in": "query",
                        "description": "分页大小",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "description": "分页大小",
                            "example": 20
                        },
                        "example": 20
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "*/*": {
                                "schema": {
                                    "$ref": "#/components/schemas/修改分页查询参数"
                                }
                            }
                        }
                    }
                },
               // operation接口级别决定使用哪一种security方案
                "security": [
                    {
                        "Authorization": []
                    }
                ]
            }
        }
    },
    "components": {
        // 定义security方案
        "securitySchemes": {
            "Authorization": {
                "type": "http",
                "scheme": "bearer"
            }
        }
    }
}

在Operation节点的规范定义如下:

image

https://spec.openapis.org/oas/latest.html#fixed-fields-7

Knife4j这样处理我觉得是合理的?

lly-ke commented 7 months ago

    @Bean
    public OpenAPI customOpenAPI() {
        return new OpenAPI()
                // .info(new Info().title("My API").version("1.0")) // API信息
                .addSecurityItem(new SecurityRequirement().addList("Access-Token")) // 安全需求
                .components(new Components()
                        .addSecuritySchemes("Access-Token", new SecurityScheme()
                                .type(SecurityScheme.Type.APIKEY)
                                .in(SecurityScheme.In.HEADER)
                                .name("Access-Token"))); // 安全模式
    }

    @Bean
    public OpenApiCustomiser securityCustomiser() {
        return openApi -> {
            openApi.getPaths().values().forEach(pathItem -> {
                // 给每个接口添加安全需求

                pathItem.readOperations().forEach(operation -> {
                    operation.addSecurityItem(new SecurityRequirement().addList("Access-Token")); // 添加安全需求
                });
            });
        };
    }

引入OpenApiCustomiser bean