在springdoc-openapi-ui中启用授权按钮以进行Bearer令牌身份验证(JWT)

49
如何在springdoc-openapi-ui(OpenAPI 3.0 /swagger-ui.html)中启用“授权”按钮,例如JWT的Bearer令牌认证。

哪些注释必须添加到Spring@Controller@Configuration类?

授权按钮

Bearer令牌认证的授权表单

4个回答

82

我更倾向于使用 Bean 初始化而不是注解。

import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info; 
import io.swagger.v3.oas.models.security.SecurityRequirement; 
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;

@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上编写安全性。


5
添加导入命令,因为可选项较少。翻译后的代码如下:import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.security.SecurityRequirement; import io.swagger.v3.oas.models.security.SecurityScheme; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.util.StringUtils; - Mr Special
1
如果您创建了全局安全模式,如何告诉Swagger特定的端点是公开的,不应标记为私有? - Luke
@rios0rios0 你说得对。在构造函数参数上注释“@Value”是没有必要的。随意更改和改进代码即可。 - JenkaBY
@JenkaBY,很抱歉,我不能编辑。StackOverflow 给了我一个错误信息:“编辑队列目前已满 - 请几分钟后再试!”我尝试了一个小时。你能编辑吗? - rios0rios0
所有操作默认使用定义的bean配置吗?因为即使我不使用@SecurityRequirement(name = "some name"),定义的授权仍然会添加到我的API操作中。这让我很困扰。我需要添加它们吗?如果我只有一种授权类型。我想当你有多种授权方式时,这是有意义的,那么生成的API操作会有所不同吗? - cvetan
显示剩余3条评论

63

使用注释@io.swagger.v3.oas.annotations.security.SecurityScheme@Configuration bean中定义OpenAPI 3.0的全局安全方案:

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

}

使用@io.swagger.v3.oas.annotations.Operation注释每个@RestController方法,要求Bearer Token身份验证(JWT),并引用定义的安全方案:

在@RestControler方法上添加@Operation注释,并参考定义的安全方案,要求Bearer Token身份验证(JWT)。

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

我也在尝试这个。我曾经认为,在授权对话框中添加身份验证令牌后,swagger会自动将其添加到所有后续请求的标头中.. 但似乎不是这样。 - 1977
有没有一种方法可以配置@SecurityScheme以处理https请求?任何想法将不胜感激。 - pratham gn
各位不要忘记,如果您将JWT传递到标头中,则必须在SecurityScheme中添加“in = SecuritySchemeIn.HEADER”。 - lemario

33

如果您想避免在@RestController中的每个@Operation上注释security属性,您可以在类级别添加此属性以影响控制器的每个操作。

请不要忘记您的配置bean需与其他示例中的相同:

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

在类级别添加安全要求

只需在您希望限制API调用的那些类上使用@SecurityRequirement(name="bearerAuth")。请注意,这些注释是继承的,因此您也可以将它们添加到任何接口中。

使用所需的注释创建标记接口:

@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令牌。 enter image description here

在方法级别添加安全要求

正如另一篇帖子中所说,您必须将@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;
    }

}

这只限制了第一个操作,而不是第二个。 输入图像描述


谢谢,你帮了我大忙!不过,如果你把“请不要忘记…”这句话放在你的回答开头,那就更好了,这样我就可以省下一小时的调试时间了 :) 我对“在方法级别添加安全要求”不感兴趣,所以我在那里停止阅读你的回答 :) - Honza Zidek

1
我找到了一个更清洁的解决方案。 对我来说它运行得很好。
感谢 @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));
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接