Включить кнопку авторизации в springdoc-openapi-ui для аутентификации токена носителя (JWT)

Как включить кнопку "Авторизовать" в springdoc-openapi-ui (OpenAPI 3.0/swagger-ui.html) для аутентификации токена-носителя, например JWT.

Какие аннотации нужно добавить в Spring @Controller а также @Configuration классы?

4 ответа

Решение

Определите глобальную схему безопасности для OpenAPI 3.0 с помощью аннотации @io.swagger.v3.oas.annotations.security.SecurityScheme в @Configuration фасоль:

@Configuration
@OpenAPIDefinition(info = @Info(title = "My API", version = "v1"))
@SecurityScheme(
    name = "bearerAuth",
    type = SecuritySchemeType.HTTP,
    bearerFormat = "JWT",
    scheme = "bearer"
)
public class OpenApi30Config {

}

Аннотировать каждый @RestController метод, требующий аутентификации токена-носителя (JWT) с @io.swagger.v3.oas.annotations.Operation ссылка на определенную схему безопасности:

@Operation(summary = "My endpoint", security = @SecurityRequirement(name = "bearerAuth"))

Я предпочитаю использовать инициализацию bean вместо аннотации.

@Configuration
public class OpenApi30Config {

  private final String moduleName;
  private final String apiVersion;

  public OpenApi30Config(
      @Value("${module-name}") String moduleName,
      @Value("${api-version}") String apiVersion) {
    this.moduleName = moduleName;
    this.apiVersion = apiVersion;
  }

  @Bean
  public OpenAPI customOpenAPI() {
    final String securitySchemeName = "bearerAuth";
    final String apiTitle = String.format("%s API", StringUtils.capitalize(moduleName));
    return new OpenAPI()
        .addSecurityItem(new SecurityRequirement().addList(securitySchemeName))
        .components(
            new Components()
                .addSecuritySchemes(securitySchemeName,
                    new SecurityScheme()
                        .name(securitySchemeName)
                        .type(SecurityScheme.Type.HTTP)
                        .scheme("bearer")
                        .bearerFormat("JWT")
                )
        )
        .info(new Info().title(apiTitle).version(apiVersion));
  }
}

Строка кода

.addSecurityItem(new SecurityRequirement().addList(securitySchemeName))

позволяет добавить глобальную схему безопасности и избавиться от записи безопасности для каждой @Operation метода.

Если вы хотите избежать аннотирования каждого внутри вашего @RestController с security атрибут, вы можете добавить его на уровне класса, влияя на каждую операцию вашего контроллера.

Добавление требований безопасности на уровне класса

Все, что вам нужно сделать, это просто использовать @SecurityRequirement(name = "bearerAuth")в тех классах, в которых вы хотите ограничить вызовы API. Обратите внимание, что эти аннотации наследуются, поэтому вы также можете добавить их в любой интерфейс.

Создайте интерфейс маркера с необходимой аннотацией:

      @SecurityRequirement(name = "bearerAuth")
public interface SecuredRestController {
}

Добавьте интерфейс маркера к тем контроллерам, где вы хотите применить ограничение ко всем операциям, например:

      @RestController
@RequestMapping("/hello")
public class HelloController implements SecuredController {

    @GetMapping
    public String hello() {
        return "Hello World";
    }

    @GetMapping("/{name}")
    public String helloWithName(@PathVariable String name) {
        return "Hello " + name;
    }

}

Вы можете сделать это без интерфейса маркера, просто говоря:

      @RestController
@RequestMapping("/hello")
@SecurityRequirement(name = "bearerAuth")
public class HelloController {
...
}

Теперь у вас есть защищенные обе операции и требуется токен JWT.

Добавление требований безопасности на уровне метода

Как было сказано в другом посте, вам нужно добавить @SecurityRequirement на ваш @Operation аннотация вашего метода.

      @RestController
@RequestMapping("/hello")
public class HelloController {

    @GetMapping
    @Operation(summary = "My endpoint", security = @SecurityRequirement(name = "bearerAuth"))
    public String hello() {
        return "Hello World";
    }

    @GetMapping("/{name}")
    public String helloWithName(@PathVariable String name) {
        return "Hello " + name;
    }

}

Это ограничивает только первую операцию, но не вторую.

Не забывайте, что ваш компонент конфигурации должен быть таким же, как в другом примере:

      @Configuration
@OpenAPIDefinition(info = @Info(title = "My API", version = "v1"))
@SecurityScheme(
    name = "bearerAuth",
    type = SecuritySchemeType.HTTP,
    bearerFormat = "JWT",
    scheme = "bearer"
)
public class OpenApi30Config {
}

Я нашел более чистое решение. Он отлично работает для меня.

Спасибо @JenkaBY.

      package com.aliyun.horoscope.verse.configuration;

import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.springdoc.core.customizers.OpenApiCustomiser;
import org.springframework.stereotype.Component;

@Component
public class AuthOpenApiCustomizer implements OpenApiCustomiser {
    @Override
    public void customise(OpenAPI openApi) {
        var securitySchemeName = "bearerAuth";
        openApi.getComponents().addSecuritySchemes(securitySchemeName, new SecurityScheme().type(SecurityScheme.Type.HTTP).scheme("bearer").bearerFormat("JWT"));
        openApi.addSecurityItem(new SecurityRequirement().addList(securitySchemeName));
    }
}
Другие вопросы по тегам