Swagger Codegen CLI Java客户端-如何正确使用它



我现在正在玩我的jersey2 rest服务。为了更好地概述给定的服务(描述、类型等),我大量使用了swagger (swagger-jersey2-jaxrs)。因此,我能够生成我的服务描述(swagger.json),我可以通过swagger ui查看和探索它们。

现在我需要创建一些客户端来使用这些服务。我遇到了swagger codegen cli,这是一个很好的工具,可以生成客户端和许多不同的语言(在我的情况下是java)。我能够生成api客户端和正在使用的模型。

这里我面临第一个问题。REST服务和swagger描述受http基本认证保护。我读了文档,它给了我一些暗示,有可能使用基本验证。在这一点上,我必须提到,从我的观点来看,文档非常糟糕。它说:

-a,——auth在远程获取swagger定义时添加授权头。传入一个url编码的字符串name:header,用逗号分隔多个值。

我想到的第一件事是在http头传递一个字符串,但这不起作用,甚至谷歌如何使用基本认证与swagger cli没有导致一些明确的答案。经过多次尝试和错误之后,我(我使用的是CLI 2.1.2)终于找到了正确的格式:

java -jar swagger-codegen-cli-2.1.2.jar generate -a "Authorization: Basic YWRtaW46YWRtaW4=" -i http://localhost:8080/webproject/restapi/swagger.json -l java -o restclient

其中YWRtaW46YWRtaW4=是admin的base64编码值:在我的例子中是admin。

到目前为止一切顺利。生成的java客户机也必须使用基本认证。我看了看ApiClient的方法,找到了setUsername和setPassword。我认为这种方法使客户能够使用基本的权限,而不是运气。

所以我更深入地研究了生成的类,特别是apicclient和几个生成的ApiService类。我发现setUsername和setPassword没有效果,因为以下原因:

/**
   * Helper method to set username for the first HTTP basic authentication.
   */
  public void setUsername(String username) {
    for (Authentication auth : authentications.values()) {
      if (auth instanceof HttpBasicAuth) {
        ((HttpBasicAuth) auth).setUsername(username);
        return;
      }
    }
    throw new RuntimeException("No HTTP basic authentication configured!");
  }

,其中HashMap同时定义如下:

// Setup authentications (key: authentication name, value: authentication).
authentications = new HashMap<String, Authentication>();
// Prevent the authentications from being modified.
authentications = Collections.unmodifiableMap(authentications);

认证哈希映射变成不可变的,但是为什么?目的是什么?此外,在ApiClinet中没有帮助方法来生成所需的auth对象,所以我做了以下操作:

1)注释掉authentications Collections.unmodifiableMap(authentications)这行,这样hashmap就可以再次修改了

2)手动创建所需的auth对象

HttpBasicAuth authentication = new HttpBasicAuth(); 
authentication.setUsername("admin");
authentication.setPassword("admin");

3)将auth对象添加到apicclients的身份验证hashmap中:

ApiClient apiClient = new ApiClient();
apiClient.setBasePath(basePath);
apiClient.getAuthentications().put("basic", authentication);

4)修改invokeApi方法(apicclient .java)

public String invokeAPI(String path, String method, Map<String, String> queryParams, Object body, Map<String, String> headerParams, Map<String, String> formParams, String accept, String contentType, String[] authNames) throws ApiException {
String authNames2[] = {"basic"};
updateParamsForAuth(authNames2, queryParams, headerParams);
//updateParamsForAuth(authNames, queryParams, headerParams);
...

步骤4是必要的,因为ApiServices调用apiClient方法的方式如下:

String[] authNames = new String[] {  };
String response = apiClient.invokeAPI(path, "POST", queryParams, postBody, headerParams, formParams, accept, contentType, authNames);

另一个可能的解决方案是在每个apisservice中定义身份验证哈希映射的Key,如:

String[] authNames = new String[] { "basic" };

在做了所有的修改之后,一切都如预期的那样工作,但我不认为这是一个自动生成的rest客户端背后的想法。所以我的问题是:我是否遗漏了一些要点,或者我是否应该认为swagger生成的客户端(在这种情况下是java)更多的是正在开发的beta解决方案?请理解我的意思,我认为整个swagger框架(jersey2支持,openapi, swaggerui, codegen)是一个伟大的东西,我感谢开发人员的努力,但我想使用正确的codegen,我不认为背后的想法是必须以这种方式定制生成的ApiClient和apisservices。

问题是您的规范没有提及您想要使用的安全性类型(也称为安全性定义)或哪个安全性定义应用于哪个端点。

这里有swagger规范,但它并没有说明全部情况。

你需要做的是1。设置安全定义。下面是一个简单的基本http认证定义:

securityDefinitions:
  basic:
    type: basic
    description: HTTP Basic Authentication. 

和2。在结束点使用该安全定义。

paths:
  /:
    get:
      security:
       - basic: []
      responses:
        200:
          description:  OK

然后重新生成swagger客户端代码。它应该正确地设置不可变映射和authNames数组。

如前所述,如果您不想修改现有代码,您可以在自定义配置中扩展ApiClient,例如

@Configuration
public class Config {
  @Value("${baseUrl}")
  private String baseUrl;
  protected class AuthApiClient extends ApiClient {
    public AuthApiClient() {
      super();
    }
    @Override
    public <T> T invokeAPI(final String path, final HttpMethod method,
            final MultiValueMap<String, String> queryParams, final Object body,
            final HttpHeaders headerParams, final MultiValueMap<String, Object> formParams,
            final List<MediaType> accept, final MediaType contentType,
            final String[] authNames, final ParameterizedTypeReference<T> returnType)
            throws RestClientException {
            final HttpBasicAuth auth = new HttpBasicAuth();
            auth.setUsername("myUsername");
            auth.setPassword("myPassword");
            auth.applyToParams(queryParams, headerParams);
      return super.invokeAPI(path, method, queryParams, body, headerParams, formParams,
                accept, contentType, authNames, returnType);
    }
  }
  @Bean
  @Primary
  @Qualifier("MyApiClient")
  public AuthApiClient myApiClient() {
    final AuthApiClient apiClient = new AuthApiClient();
    apiClient.setBasePath(this.baseUrl);
    return apiClient;
  }
}

我就是这么做的:

 apiClient.addDefaultHeader("Authorization", "Basic " + base64Bearer);

我正在使用swagger-codegen。版本3.0.35没有任何安全定义的API规范

最新更新