将 REST 客户端与 header 一起使用时获取 ssl.SSLHandshakeException 但与 PostMan 配合使用时效果很好
Getting ssl.SSLHandshakeException when using REST client with header but works fine with PostMan
我有一个外部 REST 资源,详细信息如下:
- URL:
abc.com/orders
(域名同https
)
- 我需要将 UserID 作为 HTTP header 传递,键 "user" 值为 "abcd"
- 这会 return 一个 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();
}
但是我遇到了异常,尽管它与 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.access0(WebResource.java:74)
at com.sun.jersey.api.client.WebResource$Builder.get(WebResource.java:509)
我试着搜索了一下,发现我需要从那个 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)
这些是使您的程序运行的说明。顺便说一句,我在 windows,使用 google chrome。
您确实需要证书。
1) 首先,转到url(无论是网站还是restful服务),让我们选择google.com。右键单击页面并单击 "inspect"。
2) 转到安全选项卡。
3) 到达那里后,单击 "view certificate"。
将弹出 window,其中包含站点证书的详细信息。
4) 转到 "certification path" 选项卡。然后双击层次结构中所需的证书。
会弹出一个新的window:
我在本例中选择了名为 "Google trust services..." 的根证书,但您可以选择更具体的证书,例如 "Google Internet Authority G3"。我认为它越具体,它提供的安全性就越高(但我不确定)。
5) 转到 "Details" 选项卡并选择您的证书名称:
6) 点击"Copy To File",然后选择名称和保存位置。我将我的保存在桌面上并将其命名为 "test.cer".
现在您已完成导出证书。接下来,您想将它添加到 jvm 的信任库中。
1) 查看您的应用程序在哪个 JRE 上 运行,例如我的计算机上只有一个 JRE(不包括与 JDK 捆绑在一起的那个)。它位于此处:
存储证书的目标文件是cacerts:
2) 以管理员身份打开 cmd 并执行 cd "C:\Program Files\Java\jre-10.0.1\lib\security"
(在我的例子中是 cacerts 的路径)。
3) 发出以下命令:
keytool -import -storepass changeit -noprompt -alias *alias* -keystore cacerts -trustcacerts -file *path_to_certificate*
请注意,别名可以是任何东西,无论您如何称呼您的文件,只要它不与信任库中已有的其他证书的别名冲突即可。
在我的例子中,我发出这个:
4) 您现在可以发出此命令:keytool -list -keystore cacerts -alias *alias*
以确保您的证书已添加。当您发出此命令时,它会询问您的密码。在第三步中,我给你的命令有这个选项:-storepass changeit
,所以你的密码将是 changeit
.
就我而言,一切都很好。
5) 现在您可以重新启动您的应用程序,它应该可以工作了。有人建议重启电脑,不知道有没有必要
伙计!以上都不需要!!!
只需在 Rest Api 代码之前传递 RestAssured.useRelaxedHTTPSValidation();
。
完成!`
我有一个外部 REST 资源,详细信息如下:
- URL:
abc.com/orders
(域名同https
) - 我需要将 UserID 作为 HTTP header 传递,键 "user" 值为 "abcd"
- 这会 return 一个 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();
}
但是我遇到了异常,尽管它与 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.access0(WebResource.java:74)
at com.sun.jersey.api.client.WebResource$Builder.get(WebResource.java:509)
我试着搜索了一下,发现我需要从那个 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)
这些是使您的程序运行的说明。顺便说一句,我在 windows,使用 google chrome。
您确实需要证书。
1) 首先,转到url(无论是网站还是restful服务),让我们选择google.com。右键单击页面并单击 "inspect"。
2) 转到安全选项卡。
3) 到达那里后,单击 "view certificate"。
将弹出 window,其中包含站点证书的详细信息。
4) 转到 "certification path" 选项卡。然后双击层次结构中所需的证书。
会弹出一个新的window:
我在本例中选择了名为 "Google trust services..." 的根证书,但您可以选择更具体的证书,例如 "Google Internet Authority G3"。我认为它越具体,它提供的安全性就越高(但我不确定)。
5) 转到 "Details" 选项卡并选择您的证书名称:
6) 点击"Copy To File",然后选择名称和保存位置。我将我的保存在桌面上并将其命名为 "test.cer".
现在您已完成导出证书。接下来,您想将它添加到 jvm 的信任库中。
1) 查看您的应用程序在哪个 JRE 上 运行,例如我的计算机上只有一个 JRE(不包括与 JDK 捆绑在一起的那个)。它位于此处:
存储证书的目标文件是cacerts:
2) 以管理员身份打开 cmd 并执行 cd "C:\Program Files\Java\jre-10.0.1\lib\security"
(在我的例子中是 cacerts 的路径)。
3) 发出以下命令:
keytool -import -storepass changeit -noprompt -alias *alias* -keystore cacerts -trustcacerts -file *path_to_certificate*
请注意,别名可以是任何东西,无论您如何称呼您的文件,只要它不与信任库中已有的其他证书的别名冲突即可。
在我的例子中,我发出这个:
4) 您现在可以发出此命令:keytool -list -keystore cacerts -alias *alias*
以确保您的证书已添加。当您发出此命令时,它会询问您的密码。在第三步中,我给你的命令有这个选项:-storepass changeit
,所以你的密码将是 changeit
.
就我而言,一切都很好。
5) 现在您可以重新启动您的应用程序,它应该可以工作了。有人建议重启电脑,不知道有没有必要
伙计!以上都不需要!!!
只需在 Rest Api 代码之前传递 RestAssured.useRelaxedHTTPSValidation();
。
完成!`