Swagger UI 将身份验证令牌传递给标头中的 API 调用

Posted

技术标签:

【中文标题】Swagger UI 将身份验证令牌传递给标头中的 API 调用【英文标题】:Swagger UI passing authentication token to API call in header 【发布时间】:2016-01-30 20:06:06 【问题描述】:

我是 Swagger 的新手。

我正在使用 Swagger UI 来生成 swagger 文档。我有两个 API 调用。第一个调用是根据用户名和密码生成令牌。第二次调用需要第一次调用生成的令牌。

如何使用 Swagger UI 为第二次通话设置该令牌?

【问题讨论】:

会尽力让你知道 【参考方案1】:

@ApiImplicitParams@ApiImplicitParam 应该可以解决问题:

@GET
@Produces("application/json")
@ApiImplicitParams(
    @ApiImplicitParam(name = "Authorization", value = "Authorization token", 
                      required = true, dataType = "string", paramType = "header") )
public String getUser(@PathParam("username") String userName) 
    ...

来自documentation:

您可能希望手动描述操作参数。这可能有多种原因,例如:

使用不使用 JAX-RS 注释的 Servlet。 想要隐藏定义的参数并用完全不同的定义覆盖它。 描述在到达 JAX-RS 实现之前由过滤器或其他资源使用的参数。

Swagger UI 将更新,以便您可以从那里发送您的令牌。无需更改 html


注意: 前段时间,在使用 Swagger 记录 REST API 时,我意识到仅添加 @ApiImplicitParam 是不够的(即使您只有一个参数)。无论如何,您也必须添加@ApiImplicitParams

【讨论】:

如何通过添加用户名、密码和授权类型等参数从 POST /oauth/token 获取令牌?因为在 swagger UI 中只列出了参数节点如何在那里添加自定义参数?【参考方案2】:

我对 2.9.2 Swagger 版本的配置,在 Swagger UI 上添加授权并发送 Bearer 令牌

    @Configuration
    public class SwaggerConfiguration

        //...

          @Bean
          public Docket api(ServletContext servletContext) 
            return new Docket(DocumentationType.SWAGGER_2)...
                .securitySchemes(Arrays.asList(apiKey()))
                .securityContexts(Collections.singletonList(securityContext()));
          

          private SecurityContext securityContext() 
            return SecurityContext.builder().securityReferences(defaultAuth()).forPaths(PathSelectors.regex("/.*")).build();
          

          private List<SecurityReference> defaultAuth() 
            final AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
            final AuthorizationScope[] authorizationScopes = new AuthorizationScope[]authorizationScope;
            return Collections.singletonList(new SecurityReference("Bearer", authorizationScopes));
          

          private ApiKey apiKey() 
            return new ApiKey("Bearer", "Authorization", "header");
          
     

【讨论】:

【参考方案3】:

另一个选项是添加globalOperationParameters。它将在每个端点中添加一个授权字段。

定义授权头参数:

Parameter authHeader = new ParameterBuilder()
  .parameterType("header")
  .name("Authorization")
  .modelRef(new ModelRef("string"))
  .build();

将其添加到Docket 配置中:

return new Docket(DocumentationType.SWAGGER_2)
    .select()
    .apis(...)
    .paths(...)
    .build()
    .apiInfo(...)
    .globalOperationParameters(Collections.singletonList(authHeader));

它看起来像这样:

【讨论】:

【参考方案4】:

有一个 hack 可以通过使用 responseInterceptor 和 requestInterceptor 来工作

首先使用responseInterceptor 捕获第一个API 调用的响应并保存令牌(在示例中为本地存储),然后使用requestInterceptorAuthorization 标头与保存的令牌一起添加。

            const ui = SwaggerUIBundle(
               ...
                responseInterceptor:
                    function (response) 
                        if (response.obj.access_token) 
                            console.log(response.obj.access_token)
                            const token = response.obj.access_token;
                            localStorage.setItem("token", token)
                        

                        return response;
                    ,
                requestInterceptor:
                    function (request) 
                        console.log('[Swagger] intercept try-it-out request');
                        request.headers.Authorization = "Bearer " + localStorage.getItem("token");
                        return request;
                
           

【讨论】:

【参考方案5】:

您必须自定义 swagger index page 才能实现我相信的目标。

您可以隐藏输入“input_apiKey”并为用户名和密码添加两个输入。然后您进行 ajax 调用以使用您的令牌更新隐藏的输入。

【讨论】:

【参考方案6】:

这是一个老问题,但这是我最近使用 2.7.0 版本为我的 JWT 令牌解决的方法

在您的招摇配置中,在SecurityConfiguration bean 下方添加。重要的部分是将第五个参数留空或为空。

@Bean
    public SecurityConfiguration securityInfo() 
        return new SecurityConfiguration(null, null, null, null, "", ApiKeyVehicle.HEADER,"Authorization","");
    

securitySchemes(Lists.newArrayList(apiKey())) 添加到您的主Docket bean。

@Bean
    public Docket docket()
    
        return new Docket(DocumentationType.SWAGGER_2).select()
            .....build().apiInfo(...).securitySchemes(Lists.newArrayList(apiKey()));
    


    private ApiKey apiKey() 
        return new ApiKey("Authorization", "Authorization", "header");
     

然后在 UI 中,您需要点击 Authorize 按钮并输入“Bearer access_token”(用于授权文本框),其中 access_token 是 jWT 令牌服务器提供的令牌。

此授权一经保存,将对所有端点生效。为每个端点添加单独的文本字段看起来非常麻烦。

【讨论】:

这是 Spring 项目特有的吗? 是的,Bean 是一个 Spring 概念。自动配置拾取适用于 Spring Boot。如果您有 Java 配置,那么该配置的调用者可以是非 Spring 框架,但在这种情况下,它适用于 Spring。 @SabirKhan 如何在没有 spring-fox 的情况下实现它?我正在使用 springdoc-openapi-ui (1.3.2)。但仍然面临同样的问题。我的 Spring Boot 版本是 2.2.6。因此需要删除 spring-fox。 @iaL:我不确定,如果找到有用的,会尝试查找并通知您。【参考方案7】:

将 SpringDoc 与 springdoc-openapi-maven-plugin 一起使用,我的选择是使用 SwaggerConfig.Java:

@Configuration
public class SwaggerConfiguration  
    @Bean
    public OpenAPI customOpenAPI(@Value("$project.version") String appVersion) 
        OpenAPI openApi = new OpenAPI();
                openApi.info(
                    new Info()
                .title("Title Example")
                .version(appVersion)
                .description("Swagger server created using springdocs - a library for OpenAPI 3 with spring boot.")
                );

                openApi.components(
                        new Components().addSecuritySchemes("bearer-jwt",
                new SecurityScheme().type(SecurityScheme.Type.HTTP).scheme("bearer").bearerFormat("JWT")
                        .in(SecurityScheme.In.HEADER).name("Authorization"))
                );

                openApi.addSecurityItem(
                        new SecurityRequirement().addList("bearer-jwt", Arrays.asList("read", "write"))
                );

        return openApi;
    

【讨论】:

以上是关于Swagger UI 将身份验证令牌传递给标头中的 API 调用的主要内容,如果未能解决你的问题,请参考以下文章

Springboot:将从swagger UI捕获的JWT令牌自动传递给下游(服务到服务)API调用

为啥加特林不将身份验证令牌从 POST 返回正文发布到 GET 标头

在重定向到新的 SPA 页面时在标头中传递身份验证令牌

使用身份验证标头发出跨域请求

下载文件时如何传递身份验证令牌?

如何将标头身份验证承载中的令牌发送到浏览器