当前位置: 首页 > 知识库问答 >
问题:

以编程方式添加安全方案时,架构从组件中消失

郑曜灿
2023-03-14

我最近从Springfox转换为Springdoc-openapi,以便为Spring Boot Rest API服务生成OpenAPI。

在我加了一个安全方案之前,一切都运行得很好。一旦我这样做了,我的计划就不再出现了,SwaggerUI页面上出现了一个错误:

Could not resolve reference: Could not resolve pointer: /components/schemas/Ping does not exist in document

pom.xml的片段:

        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-ui</artifactId>
            <version>1.5.1</version>
        </dependency>
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-hateoas</artifactId>
            <version>1.5.1</version>
        </dependency>
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-security</artifactId>
            <version>1.5.1</version>
        </dependency>

来自配置得代码段:

    @Bean
public GroupedOpenApi apiV1() {
    String[] paths = {"/v1/**"};
    String[] packagesToScan = {"com.test.controller"};
    return GroupedOpenApi.builder()
            .group("v1")
            .packagesToScan(packagesToScan)
            .pathsToMatch(paths)
            .addOpenApiCustomiser(buildV1OpenAPI())
            .build();
}

@Bean
public GroupedOpenApi apiV2() {
    String[] paths = {"/v2/**"};
    String[] packagesToScan = {"com.test.controller"};
    return GroupedOpenApi.builder()
            .group("v2")
            .packagesToScan(packagesToScan)
            .pathsToMatch(paths)
            .addOpenApiCustomiser(buildV2OpenAPI())
            .build();
}

public OpenApiCustomiser buildV1OpenAPI() {
    return openApi -> openApi.info(apiInfo().version("v1"));
}

public OpenApiCustomiser buildV2OpenAPI() {
    final String securitySchemeName = "Access Token";
    return openApi -> openApi.info(apiInfo().version("v2"))
            .addSecurityItem(new SecurityRequirement().addList(securitySchemeName))
            .components(new Components().addSecuritySchemes(securitySchemeName, new SecurityScheme()
                    .type(SecurityScheme.Type.APIKEY)
                    .in(SecurityScheme.In.HEADER)
                    .name(HttpHeaders.AUTHORIZATION)));
}

// Describe the apis
private Info apiInfo() {
    return new Info()
            .title("Title")
            .description("API Description");
}

对我的v1组来说,一切都很好。我的模式出现在Swagger UI页面上,并且在生成的API-Doc的components部分中看到它们。

    "components": {
    "schemas": {
        "ApplicationErrorResponse": {
            ...
            }
        },
        "Ping": {
            ...
        }
    }
}
    "components": {
    "securitySchemes": {
        "Access Token": {
            "type": "apiKey",
            "name": "Authorization",
            "in": "header"
        }
    }
}
@Operation(summary = "Verify API and backend connectivity",
        description = "Confirm connectivity to the backend, as well and verify API service is running.")
@OkResponse
@GetMapping(value = API_VERSION_2 + "/ping", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Ping> getPingV2(HttpServletRequest request) {
    @Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
@ApiResponse(responseCode = HTTP_200,
        description = HTTP_200_OK,
        headers = {
                @Header(name = CONTENT_VERSION_HEADER, description = CONTENT_VERSION_HEADER_DESCRIPTION, schema = @Schema(type = "string")),
                @Header(name = DEPRECATION_MESSAGE_HEADER, description = DEPRECATION_MESSAGE_HEADER_DESCRIPTION, schema = @Schema(type = "string")),
                @Header(name = DESCRIPTION_HEADER, description = DESCRIPTION_HEADER_DESCRIPTION, schema = @Schema(type = "string"))
        })
public @interface OkResponse {
}

我的v1映射的定义类似。

共有1个答案

洪国兴
2023-03-14

因此,当仅仅依赖OpenApiCustomiser来创建OpenAPI时,扫描的组件将被忽略,或者至少仅用定制器中指定的组件覆盖(我也可以以编程方式添加我的所有模式,但这将非常麻烦地维护)。

将我的配置更改为以下内容解决了我的问题:

@Bean
public OpenAPI customOpenAPI() {
    final String securitySchemeName = "Access Token";
    return new OpenAPI()
            .addSecurityItem(new SecurityRequirement().addList(securitySchemeName))
            .components(new Components().addSecuritySchemes(securitySchemeName, new SecurityScheme()
                    .type(SecurityScheme.Type.APIKEY)
                    .in(SecurityScheme.In.HEADER)
                    .name(HttpHeaders.AUTHORIZATION)))
            .info(apiInfo());
}

@Bean
public GroupedOpenApi apiV1() {
    String[] paths = {"/v1/**"};
    String[] packagesToScan = {"com.test.controller"};
    return GroupedOpenApi.builder()
            .group("v1")
            .packagesToScan(packagesToScan)
            .pathsToMatch(paths)
            .addOpenApiCustomiser(buildV1OpenAPI())
            .build();
}

@Bean
public GroupedOpenApi apiV2() {
    String[] paths = {"/v2/**"};
    String[] packagesToScan = {"com.test.controller"};
    return GroupedOpenApi.builder()
            .group("v2")
            .packagesToScan(packagesToScan)
            .pathsToMatch(paths)
            .addOpenApiCustomiser(buildV2OpenAPI())
            .build();
}

public OpenApiCustomiser buildV1OpenAPI() {
    return openApi -> openApi.info(openApi.getInfo().version("v1"));
}

public OpenApiCustomiser buildV2OpenAPI() {
    return openApi -> openApi.info(openApi.getInfo().version("v2"));
}

// Describe the apis
private Info apiInfo() {
    return new Info()
            .title("Title")
            .description("API Description.");
}

虽然这在技术上也会将Authorize按钮和安全方案添加到v1组中,但可以忽略它,因为这些API端点无论如何都不安全(内部API,它们应该很快就会消失)。

这可能是一个更好的解决方案,因为信息在组之间基本相同。

 类似资料:
  • 我正在尝试在Android上添加Wifi网络,我想知道如何连接到不广播其SSID的Wifi网络(它是否有空SSID或带有\0s的清晰SSID)。 这是我目前用于广播其SSID的Wifi网络的内容:

  • 问题内容: 我想在头部分中以编程方式添加StyleSheets,但是我看到的示例之一似乎需要多行代码才能仅添加一个样式表,即使我可能需要很多: 示例代码: 我也使用方法,但是它也不起作用。对象null抛出了错误。 我也使用了和东西,但是它们抛出了文字错误,这是我认为的常见错误。 我使用此代码: 起初它起作用,但是当我更改页面时,它停止工作。 我正在使用“母版页”,并且正在文件中编写这些代码,也有人

  • 我正在使用高级自定义字段(ACF ),并尝试以编程方式向现有组(group_5621b0871e1b1)添加一个中继器,但它不起作用。相同的代码适用于文本字段,但不适用于repeater。 在我的插件中: 它显示了group_5621b0871e1b1组中的此错误: 我做错什么了吗?有没有可能以编程方式添加一个中继器。

  • 我试图在logback中动态添加一个appender。这是我的代码。 它工作正常,但仅适用于添加追加器的特定记录器。有没有办法让它适用于应用程序中的所有记录器?我正在寻找一种动态添加和删除追加器的方法。

  • 我有一个模型,其中有一个@列(nullable=false)注释HiberNate和所有字段有nullable=false,我想以编程方式添加一些新的注释,如@NotNull和@ApiModelProperty(必需=true)-用于招摇过市。 所以,我希望能够从我的应用程序的模型中解析所有字段,获得现有的注释,并在此基础上添加新的注释。这能做到吗? 更新:问题是每次添加一个新字段,如果它不能为空

  • 我正在创建一个UI(以编程方式),它将显示两个主要部分 > 第一部分将显示一个视频播放器 第二部分将展示一个带有更多视频的UITableView 我已经成功地完成了第一部分,它正在工作,它占据了屏幕顶部的一小部分 使用相同的逻辑,我试图在主容器视图中添加一个UITableView,但我只能看到一个空的tableView 我还尝试在调用cellForRowAt时记录消息,但没有打印任何内容,我得出结