java - 我用 Java 编写的 Java 客户端库出现 SSL 错误。遵循文档后请求仍然失败

标签 java http ssl http-headers

我正在创建一个电子商务网站,我计划使用的代发货商之一提供了一个可用于自动下达和跟踪订单的 API。即使他们有多种语言(PHP、Python、Ruby、Node)的客户端,但他们还没有 Java 客户端,所以我决定自己写一个。我正在尝试对其进行测试,但我一直收到此错误

Hostname in certificate didn't match: <api.theprintful.com> != <behappy.me> OR <behappy.me> OR <www.behappy.me>

我已按照他们的文档说明进行操作:

Some API requests (like the Product catalog and Country codes) are available without an  
API key, but for majority of requests you will need to authenticate your store.
...
To perform authorization, you need to add the Authorization header with a Base64 encoded
API key when performing a request. So if the API key is vv0gtldg-1d7v-qclq:e2vv-
lmhg676ak0z1, then you need to add this header to the API request:
Authorization: Basic dnYwZ3RsZGctMWQ3di1xY2xxOmUydnYtbG1oZzY3NmFrMHox

我已经按照指示去做了

//constructor that is used to make the object
public ProductsRequest(String apiKey)
{
    super();
    this.apiKey = apiKey;
    this.encodedApiKey = codec.encodeBase64String(apiKey.getBytes());
}

//function that is used to call the api
public List<Product> getAllProductList(String path)
{
    //the list of products that will be returned
    List<Product> returnedProducts = null;

    //set the endpoint that will be used to get the list of products
    httpGet = new HttpGet(path);
    String basicString = "Basic "+this.encodedApiKey;
    httpGet.addHeader("Authorization",basicString.substring(0,basicString.length()-2));

    try
    {
        response = httpClient.execute(httpGet);
        if(response.getStatusLine().getStatusCode() == 200)
        {
            entity = response.getEntity();
            jsonResponse = EntityUtils.toString(entity);
            Type listType = new TypeToken<List<Product>>(){}.getType();
            JsonNode root = mapper.readTree(jsonResponse);
            ArrayNode products = (ArrayNode) root.path("result");
            returnedProducts = (List<Product>) gson.fromJson(products.toString(),listType);
        }
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }

    return returnedProducts;
}

我不明白为什么会出现此错误。我试着给公司的开发团队发邮件,他们建议我尝试创建一个假的商店,这个商店没有连接到任何我可以用来测试的电子商务软件,但他们说一切看起来都很好。我尝试按照该建议进行操作,但仍然遇到相同的错误。

我找到了 this Stackoverflow 上的线程,看起来有人遇到了类似的问题。我只是想知道为什么我必须在 Java 中执行此操作,而其他语言的其他客户端库都不必经历此过程?

据我所知,我正在按照文档说明的方式对所有内容进行编码,并且我正在正确设置 header 。我需要使用不同的库吗?

我目前正在使用 apache commons-codec

<dependency>
      <groupId>commons-codec</groupId>
      <artifactId>commons-codec</artifactId>
      <version>1.4</version>
  </dependency>

和 apache http 组件

<dependency>
      <groupId>org.apache.httpcomponents</groupId>
      <artifactId>httpclient</artifactId>
      <version>4.3.2</version>
  </dependency>

我已经尝试从公司使用另一种语言的客户端库之一运行示例,并且一切正常。我知道我的代码有问题,而不是他们的 SSL 证书有问题,但我不知道是什么。

最佳答案

您的服务器正在使用服务器名称指示来根据您要求的名称提供不同的证书(这是在同一 IP 地址和端口上使用 SSL/TLS 托管多个证书所必需的)。

您可以通过以下方式检查:

openssl s_client -connect api.theprintful.com:443 -servername api.theprintful.com

openssl s_client -connect api.theprintful.com:443

SNI is currently only available since Java 7 (并且仅在客户端,计划为 Java 8 提供服务器端支持)。

使用 HttpsURLConnection 时,运行 Java 7 的应用程序应该会自动为您执行此操作。

fix for this in Apache HTTP Client is recent .您应该确保您确实在使用 4.3.2 版 Java 7。对于 4.3.1 版(即使是 Java 7)或 Java 6 上的 4.3.2,以下操作将失败:

CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet("https://sni.velox.ch/");
HttpResponse response = httpClient.execute(httpGet);

关于java - 我用 Java 编写的 Java 客户端库出现 SSL 错误。遵循文档后请求仍然失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22202591/

相关文章:

java - 使用 Java 客户端在 Apache YARN 上运行 MapReduce 应用程序

java - Spring boot - 错误的 TCP 连接处理

json - 跨域 $http 请求 AngularJS

ruby-on-rails - rails : issuing POST and other http requests from the rails console?

ssl - Heroku ACN(用于 SSL)失败 - 我的 DNS 是正确的。该怎么办?

java - Tomcat 容器能否提高 JDBC 性能/可扩展性?

java - 如何在逐个字符读写时同步代码块以将整个字/行写入输出文件?

java - 无法同时使用 @NonNull 和 @NonNull 进行注释

无法编译使用 openssl 库的 c 程序

c++ - Boost.Asio : SSL Server and Client. 服务器 SIGSEGV 和客户端短读取错误