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

n6lpvg4x  于 2022-11-23  发布在  Java
关注(0)|答案(3)|浏览(219)

我现在正在玩我的jersey 2 rest服务。为了更好地了解给定的服务(描述,类型等等),我大量使用swagger(swagger-jersey 2-jaxrs)。所以我能够生成我的服务描述(swagger.json),我可以通过swagger ui查看和探索它们。
现在,我需要创建一些客户端来使用这些服务,我遇到了swagger codegen cli,它是一个很好的工具,可以生成客户端和许多不同的语言(在我的例子中是java),我能够生成api客户端和使用中的模型。
这里我遇到了第一个问题。REST服务和swagger描述是http basic auth保护的。我读了documentation,它给了我一些提示,有可能使用basic auth。在这一点上,我必须提到,从我的Angular 来看,文档是非常差的。它说:
-a,--auth在远程提取swagger定义时添加授权头。传入URL编码的字符串name:header,并用逗号分隔多个值。
我想到的第一件事是传递一个字符串,就像在一个http头,但这不工作,甚至谷歌如何使用swagger cli基本auth没有得到一些明确的答案.经过大量的尝试和错误,我(我使用CLI 2.1.2)我终于找到了正确的格式:
“授权:基本服务器
其中YWRtaW 46 YWRtaW 4 =是admin的base64编码值:在我的例子中是admin。
到目前为止一切顺利。生成的java客户端也必须使用基本的auth。我看了一下ApiClient中的方法,发现了setUsername和setPassword。我认为这个方法可以让客户端使用基本的auth,但运气不好。
所以我更深入地研究了生成的类,特别是ApiClient和几个生成的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)行,以便散列表再次变为可修改的
2)手动创建所需的身份验证对象

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

3)将auth对象添加到apiClients身份验证散列表:

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

4)修改invokeApi方法(ApiClient.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);

另一种可能的解决方案是在每个apiService中定义身份验证散列表的Key,如下所示:

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

在做了所有的修改之后,一切都按预期运行,但我不认为这是自动生成的rest客户端背后的想法。我是否遗漏了某个要点,或者我是否应该考虑一下由昂首阔步的客户生成的(在这个例子中是java)更多的是一个正在开发中的beta解决方案?请让我正确,我认为整个swagger框架(jersey 2支持、openapi、swaggerui、codegen)是一个伟大的事情,我感谢开发人员的努力,但我想使用codegen的权利,我不'我不认为背后的想法是必须以这样的方式定制生成的ApiClient和ApiServices。

ffdz8vbo

ffdz8vbo1#

问题是您的规范没有提到您要使用的安全性类型(也称为安全性定义)或哪个安全性定义应用于哪个端点。
昂首阔步的规范是here,但它并没有说明全部情况。
您需要做的是1.设置安全定义。下面是一个简单的基本http auth定义:

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

2.在端点中使用该安全定义。

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

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

ercv8c1e

ercv8c1e2#

正如已经建议的,如果不想修改现有代码,可以在自定义配置中扩展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;
  }
}
eyh26e7m

eyh26e7m3#

这样做对我很有效:

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

我正在使用swagger-codegen.版本3.0.35和API规范,但未定义任何安全定义

相关问题