Spring Boot 和 Swagger UI。设置 JWT 令牌

问题描述 投票:0回答:7

我有一个像这样的 Swagger 配置

@EnableSwagger2
@Configuration
public class SwaggerConfig {
    @Bean
    public Docket api() {
        List<SecurityScheme> schemeList = new ArrayList<>();
        schemeList.add(new ApiKey(HttpHeaders.AUTHORIZATION, "JWT", "header"));
        return new Docket(DocumentationType.SWAGGER_2)
                .produces(Collections.singleton("application/json"))
                .consumes(Collections.singleton("application/json"))
                .ignoredParameterTypes(Authentication.class)
                .securitySchemes(schemeList)
                .useDefaultResponseMessages(false)
                .select()
                .apis(Predicates.not(RequestHandlerSelectors.basePackage("org.springframework.boot")))
                .paths(PathSelectors.any())
                .build();
    }
}

在 Swagger UI 中,当我单击“授权”按钮时,我在值字段中输入我的 JWT 令牌

eyJhbGc..nN84qrBg
。现在,我希望通过 Swagger UI 执行的任何请求都将在标头中包含 JWT。然而,事实并非如此。 没有请求包含授权标头。

我错过了什么?

spring-boot swagger swagger-ui swagger-2.0
7个回答
88
投票

原答案

Authorization: Bearer [JWT_TOKEN]
标头的支持从版本 2.9.2 开始工作

在 build.gradle 中添加了以下依赖项

compile("io.springfox:springfox-swagger2:2.9.2") {
    exclude module: 'mapstruct' // necessary in my case to not end up with multiple mapstruct versions
}
compile "io.springfox:springfox-bean-validators:2.9.2"
compile "io.springfox:springfox-swagger-ui:2.9.2"

通过

配置Swagger
@Configuration
@EnableSwagger2
@Import(springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration.class)
public class SwaggerConfiguration {

    public static final String AUTHORIZATION_HEADER = "Authorization";
    public static final String DEFAULT_INCLUDE_PATTERN = "/api/.*";
    private final Logger log = LoggerFactory.getLogger(SwaggerConfiguration.class);

    @Bean
    public Docket swaggerSpringfoxDocket() {
        log.debug("Starting Swagger");
        Contact contact = new Contact(
            "Matyas Albert-Nagy",
            "https://justrocket.de",
            "[email protected]");

        List<VendorExtension> vext = new ArrayList<>();
        ApiInfo apiInfo = new ApiInfo(
            "Backend API",
            "This is the best stuff since sliced bread - API",
            "6.6.6",
            "https://justrocket.de",
            contact,
            "MIT",
            "https://justrocket.de",
            vext);

        Docket docket = new Docket(DocumentationType.SWAGGER_2)
            .apiInfo(apiInfo)
            .pathMapping("/")
            .apiInfo(ApiInfo.DEFAULT)
            .forCodeGeneration(true)
            .genericModelSubstitutes(ResponseEntity.class)
            .ignoredParameterTypes(Pageable.class)
            .ignoredParameterTypes(java.sql.Date.class)
            .directModelSubstitute(java.time.LocalDate.class, java.sql.Date.class)
            .directModelSubstitute(java.time.ZonedDateTime.class, Date.class)
            .directModelSubstitute(java.time.LocalDateTime.class, Date.class)
            .securityContexts(Lists.newArrayList(securityContext()))
            .securitySchemes(Lists.newArrayList(apiKey()))
            .useDefaultResponseMessages(false);

        docket = docket.select()
            .paths(regex(DEFAULT_INCLUDE_PATTERN))
            .build();
        watch.stop();
        log.debug("Started Swagger in {} ms", watch.getTotalTimeMillis());
        return docket;
    }


    private ApiKey apiKey() {
        return new ApiKey("JWT", AUTHORIZATION_HEADER, "header");
    }

    private SecurityContext securityContext() {
        return SecurityContext.builder()
            .securityReferences(defaultAuth())
            .forPaths(PathSelectors.regex(DEFAULT_INCLUDE_PATTERN))
            .build();
    }

    List<SecurityReference> defaultAuth() {
        AuthorizationScope authorizationScope
            = new AuthorizationScope("global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        return Lists.newArrayList(
            new SecurityReference("JWT", authorizationScopes));
    }
}

通过
http://host:port/<context-root>/swagger-ui.html

访问用户界面

按授权所有请求并输入承载 [JWT_TOKEN]

Press authorize then enter the Bearer JWT Token

瞧,您的下一个请求将包含 JWT 标头

enter image description here

更新2022-09-24

在一系列较新的项目之后,我开始使用

springdoc-openapi
来生成基于
javadoc
的文档,从而消除了额外注释的需要。

写这篇文章给任何愿意尝试这个库的人。我会推荐它/我是这个库的快乐用户。

依赖关系

build.gradle

[...]
// swagger ui
implementation 'org.springdoc:springdoc-openapi-ui:1.6.9'
implementation 'org.springdoc:springdoc-openapi-javadoc:1.6.9'
annotationProcessor 'com.github.therapi:therapi-runtime-javadoc-scribe:0.13.0'
implementation 'com.github.therapi:therapi-runtime-javadoc:0.13.0'
[...]

声明身份验证

使用项目特定的

SecurityConfiguration.java
- 定义OpenAPI授权的模式。本例:HTTP 中的
Bearer
中的
Authorization
header

REST 控制器中的使用

import static io.swagger.v3.oas.annotations.enums.SecuritySchemeIn.HEADER; import static io.swagger.v3.oas.annotations.enums.SecuritySchemeType.HTTP; import io.swagger.v3.oas.annotations.security.SecurityScheme; @Component @SecurityScheme(name = SecurityConfiguration.SECURITY_CONFIG_NAME, in = HEADER, type = HTTP, scheme = "bearer", bearerFormat = "JWT") public class SecurityConfiguration extends WebSecurityConfigurerAdapter { [...] public static final String SECURITY_CONFIG_NAME = "App Bearer token"; [...]

中的使用应参考安全配置

SomeController.java

配置可达性

配置 openapi 规范的位置 (swagger yml) - 默认
    import static com.x.common.security.SecurityConfiguration.SECURITY_CONFIG_NAME; import io.swagger.v3.oas.annotations.security.SecurityRequirement; @RestController @RequestMapping("/api/v1/resources") @SecurityRequirement(name = SECURITY_CONFIG_NAME) public class ConnectionSyncController { /** * Documentation that will be rendered * * supports * * 1. markdown * 1. list */ @PostMapping("/{id}/sync") @DomainAuthorize(permissionType = BasePermissions.PERM_ADMIN_OPERATIONS) public void syncConnection(@PathVariable("id") Long id) {
  1. 配置
  2. /v3/api-docs
  3. 所在位置/从
    加载配置
    
    配置
  4. swagger-ui
  5. 可以与哪些后端对话
    如果我们位于代理后面,我们需要确保调用使用正确的标头进行代理,以便一切正常工作。
swagger-ui

/src/main/resources/application.yml



13
投票

    创建一个 SwaggerConfig 类。
  1. server: port: 80 # needed for swagger-ui to detect correct proxied paths correctly. # Configuration needed for the [Try out] buttons to work # this works in combination with the proxied headers # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # proxy_set_header X-Forwarded-Prefix /services/impower-facilioo; forward-headers-strategy: FRAMEWORK springdoc: swagger-ui: # where the UI configuration is located at configUrl: /[some/public/path]/v3/api-docs/swagger-config filter: true deepLinking: true # where the server API yml/json files are at (dropdown in top right corner) urls[0]: url: /[some/public/path]/v3/api-docs name: backend

      然后注释您想要将此授权标头发送到的每个 API:
    1. @Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.any()) .paths(PathSelectors.any()) .build() .apiInfo(apiInfo()) .securitySchemes(Arrays.asList(apiKey())); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("Sig-Predict REST API Document") .description("work in progress") .termsOfServiceUrl("localhost") .version("1.0") .build(); } private ApiKey apiKey() { return new ApiKey("jwtToken", "Authorization", "header"); }


4
投票
您的代码是正确的。

springfox-swagger-ui

/springfox-swagger2 版本 2.8.0 中有一个 bug,似乎 2.9.2 也是如此。我怀疑您正在使用受此错误影响的版本。 我只是降级到

2.7.0

,它工作得很好。


0
投票
authorization header

配置了我的文档。 @ApiOperation(value = "", authorizations = { @Authorization(value="jwtToken") })

就此写了一篇小文章 
authorization-field-in-swagger-ui


0
投票

@Configuration @EnableSwagger2 public class SwaggerConfig { private static final Set<String> DEFAULT_PRODUCES_CONSUMES = new HashSet<String>(Arrays.asList("application/json")); @Bean public Docket api() { ParameterBuilder parameterBuilder = new ParameterBuilder(); parameterBuilder.name("Authorization") .modelRef(new ModelRef("string")) .parameterType("header") .description("JWT token") .required(true) .build(); List<Parameter> parameters = new ArrayList<>(); parameters.add(parameterBuilder.build()); return new Docket(DocumentationType.SWAGGER_2).apiInfo(DEFAULT_API_INFO) .produces(DEFAULT_PRODUCES_CONSUMES) .consumes(DEFAULT_PRODUCES_CONSUMES) .select() .build() // Setting globalOperationParameters ensures that authentication header is applied to all APIs .globalOperationParameters(parameters); } }



0
投票

做了一些研究来改进这一点,并使用 OpenApi 来实现这一点,而不需要那个微小的令人讨厌的添加。

来源我曾经继续这样做

(做了一些小的更改/添加)

pom.xml

我有以下内容: return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.any()).paths(PathSelectors.regex("/api/v1/.*")) .build().groupName("API") .globalOperationParameters(newArrayList( new ParameterBuilder().name(HttpHeaders.AUTHORIZATION).description("Authorization token").required(true) .modelRef(new ModelRef("string")).parameterType("header").required(true).build())) .apiInfo(apiInfo());

在 application.properties 中我添加了几行(可选):

<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.5</version> <relativePath /> </parent> <properties> <java.version>16</java.version> <swagger.version>2.9.2</swagger.version> <open.api.version>1.6.9</open.api.version> </properties> <dependencies> <!-- Swagger --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>${swagger.version}</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>${swagger.version}</version> </dependency> <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-ui</artifactId> <version>${open.api.version}</version> </dependency> </dependencies>

swagger 需要有一些安全设置例外:

spring.mvc.pathmatch.matching-strategy=ant-path-matcher springdoc.swagger-ui.path=swagger-ui.html springdoc.paths-to-exclude=/swagger-resources/**

最后是使用 OpenApi 的 swagger 的实际配置:

@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) class SecurityConfiguration extends WebSecurityConfigurerAdapter { /* Specify the urls not requiring authentication. */ @Override public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers("/v3/api-docs/**", "/swagger-ui.html", "/swagger-ui/**", "/configuration/ui", "/swagger-resources/**", "/configuration/**", "/webjars/**"); } }



0
投票

Spring Boot 3 + JWT + Swagger 示例 要为 Spring Boot 3
实现 JWT 令牌的 swagger,必须遵循以下步骤 -

    添加swagger依赖-
  1. org.springdoc
    springdoc-openapi-starter-webmvc-ui
    2.0.3


  2. 接下来我们创建一个名为 SwaggerConfig 的类,它使用 Spring 框架的 @Configuration 注解来定义用于生成 Swagger 文档的 bean。我们创建一个 OpenAPI 对象,其中包含有关身份验证服务的信息,包括标题、描述。最重要的是,在此配置中,我们创建了用于承载身份验证的安全方案,指定方案名称、类型和承载格式。 @豆 公共 OpenAPI customOpenAPI() {
  3. package com.fujitsu.emom.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.info.Contact; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.security.SecurityRequirement; import io.swagger.v3.oas.models.security.SecurityScheme; /** * Configuration for swagger using OpenApi.<br/> * Notice the spring security must allow to access to the swagger ui at 'SecurityConfiguration.java'.<br/> * There are also configuration at 'application.properties' for defining the URL to swagger page. */ @Configuration public class SwaggerConfig { public static final String SCHEME_NAME = "BearerScheme"; public static final String SCHEME = "Bearer"; @Bean public OpenAPI customOpenAPI() { var openApi = new OpenAPI().info(this.apiInfo()); this.addSecurity(openApi); return openApi; } private Info apiInfo() { var contact = new Contact(); contact.setEmail("[email protected]"); contact.setName("product_admin"); contact.setUrl("http://product.com"); return new Info() .title("Product API") .description("Product description") .termsOfService("http://product.com/terms_of_service") .contact(contact) // TODO: Version should be dynamically .version("0.5.1"); } private void addSecurity(OpenAPI openApi) { var components = this.createComponents(); var securityItem = new SecurityRequirement().addList(SCHEME_NAME); openApi.components(components).addSecurityItem(securityItem); } private Components createComponents() { var components = new Components(); components.addSecuritySchemes(SCHEME_NAME, this.createSecurityScheme()); return components; } private SecurityScheme createSecurityScheme() { return new SecurityScheme().name(SCHEME_NAME).type(SecurityScheme.Type.HTTP).scheme(SCHEME); } }

    }
    

    enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.