使用带有标头的 REST 客户端时获取 ssl.SSLHandshakeException 但与 PostMan 一起工作正常

J. *_*Doe 6 java rest jersey rest-client

我有一个包含以下详细信息的外部 REST 资源:

  1. 网址:( abc.com/orders域名为https
  2. 我需要将 UserID 作为 HTTP 标头传递,键“user”值为“abcd”
  3. 这将返回一个 JSON 响应

我为此使用以下 Java 代码:

try {

            Client client = Client.create();

            WebResource webResource = client.resource("abc.com/orders");

            ClientResponse response = webResource.header("user", "abcd").accept("application/json")
                    .get(ClientResponse.class);

            if (response.getStatus() != 200) {
                throw new RuntimeException("Failed : HTTP error code : " + response.getStatus());
            }

            String output = response.getEntity(String.class);

            System.out.println("Output from Server .... \n");
            System.out.println(output);

        } catch (Exception e) {

            e.printStackTrace();

        }
Run Code Online (Sandbox Code Playgroud)

但是我得到了低于异常的结果,尽管它可以正常工作 PostMan

com.sun.jersey.api.client.ClientHandlerException: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at com.sun.jersey.client.urlconnection.URLConnectionClientHandler.handle(URLConnectionClientHandler.java:155)
    at com.sun.jersey.api.client.Client.handle(Client.java:652)
    at com.sun.jersey.api.client.WebResource.handle(WebResource.java:682)
    at com.sun.jersey.api.client.WebResource.access$200(WebResource.java:74)
    at com.sun.jersey.api.client.WebResource$Builder.get(WebResource.java:509)
Run Code Online (Sandbox Code Playgroud)

我试着搜索了一下,发现我需要从那个 URL 获取证书并添加到jdk/lib/security文件夹的某个地方。但我不知道如何继续。

使用 openssl 我得到以下输出:

user>openssl s_client -connect  abc.com:443

CONNECTED(00000214)
7832:error:14077438:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert internal error:s23_clnt.c:802:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 308 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : 0000
    Session-ID:
    Session-ID-ctx:
    Master-Key:
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1531657560
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
Run Code Online (Sandbox Code Playgroud)

Cod*_*Man 7

These are the instructions to make your program work. Btw, I am on windows, using google chrome.

You do need a certificate.

1) First, go to the url (doesn't matter if it's a website or a restful service), let's pick google.com. Right click on the page and click "inspect".

在此处输入图片说明

2) Go to the security tab.

在此处输入图片说明

3) Once, you're there, click "view certificate". 在此处输入图片说明

A window will pop up, with site's certificate's details.

4) Go to the "certification path" tab. And double click on the certificate that you want from the hierarchy. 在此处输入图片说明

A new window will pop up:

在此处输入图片说明

I chose the root certificate in this case called "Google trust services...", but you can choose a more specific one, like "Google Internet Authority G3". I think the more specific it is, the more security it provides (but I'm not sure).

5) Go to the "Details" tab and choose your certificate's name:

在此处输入图片说明

6) Click "Copy To File", then choose the name for it and where you want to save it. I saved mine on desktop and named it "test.cer".

Now you are done exporting the certificate. Next, you want to add it to jvm's truststore.

1) Look up which JRE your application is running on, for example I have only one JRE on my computer (excluding the one bundled with the JDK). It's located here:

在此处输入图片说明

The target file that stores certificates is cacerts:

在此处输入图片说明

2) Open cmd as administrator and do cd "C:\Program Files\Java\jre-10.0.1\lib\security" (path to cacerts in my case).

3) Issue the following command:

keytool -import -storepass changeit -noprompt -alias *alias* -keystore cacerts -trustcacerts -file *path_to_certificate*

Note that alias can be anything, regardless of what you called your file, as long as it doesn't clash with aliases of other certificates already in the truststore.

In my case I issue this:

在此处输入图片说明

4) You can now issue this command: keytool -list -keystore cacerts -alias *alias* to make sure your certificate was added. When you issue this command, it will ask you for your password. In step three, the command I gave your had this option: -storepass changeit, so your password will be changeit.

在此处输入图片说明

In my case everything is okay.

5) Now you can restart your application and it should work. Some people recommend restarting your computer, but I don't know if that's necessary.


小智 5

男人!以上都不需要!!!RestAssured.useRelaxedHTTPSValidation();只需在 Rest Api 代码之前传递即可。完成!`