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

我是 Swagger 的新手。

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

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

【问题讨论】:

  • 会尽力让你知道

标签: rest jersey swagger 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;
              }
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-08-17
            • 1970-01-01
            • 1970-01-01
            • 2015-02-24
            • 2021-05-14
            • 2016-10-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多