如何解决 javax.net.ssl.SSLHandshakeException 错误?

我连接到 VPN 设置库存 API,以获得产品清单,它的工作正常。一旦我从 Web 服务得到结果,我就绑定到 UI。而且我整合贝宝与我的应用程序,使快速结帐时,我面临着这个错误的付款电话。我将 servlet 用于后端进程。有人能说说怎么解决这个问题吗?

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
678828 次浏览

我相信您正在尝试使用 SSL 连接到某个东西,但是某个东西提供了一个未经 verisign 等 root 认证机构验证的证书。.默认情况下,实质上只有当试图连接的人知道对方密钥或 verisign 之类的其他投标人可以介入并说所提供的公钥确实是正确的时候,才能建立安全连接。.

所有操作系统的信任少数认证机构和较小的证书颁发者需要由一个大的认证机构认证,如果你明白我的意思..。

言归正传。.我在编写 java applet 和 java 服务器时也遇到过类似的问题(希望有一天我能写一篇完整的博客文章,讲述我是如何让所有的安全性工作的:)

实际上,我所要做的就是从服务器中提取公钥,并将其存储在 applet 中的密钥存储库中。当我连接到服务器时,我使用这个密钥存储库创建一个信任工厂,并使用这个信任工厂创建 ssl 连接。还有一些备用过程,比如向 JVM 的受信任主机添加密钥,以及在启动时修改默认的信任存储区。.

我大约两个月前这样做,现在没有源代码在我身上。.使用谷歌,你应该能够解决这个问题。如果你不能给我回信息,我可以提供你的项目相关的源代码。.不知道这是否解决了您的问题,因为您还没有提供导致这些异常的代码。此外,我工作与小应用程序认为,我不能看到为什么它不工作在 Serverlets..。

另外,由于外部 SSH 在我的办公室被禁用,我无法在周末之前得到源代码:

首先,您需要从要连接的服务器获得公共证书。这可以通过多种方式完成,比如联系服务器管理员并请求它,使用 OpenSSL 下载它,或者,因为这似乎是一个 HTTP 服务器,用任何浏览器连接到它,查看页面的安全信息,并保存证书的副本。(谷歌应该能够准确地告诉你该为你的特定浏览器做些什么。)

现在您已经将证书保存在一个文件中,您需要将它添加到 JVM 的信任存储中。在 JRE 的 $JAVA_HOME/jre/lib/security/或 JDK 的 $JAVA_HOME/lib/security中,有一个名为 cacerts的文件,它是 Java 附带的,包含著名的认证机构的公共证书。要导入新的证书,请以拥有写入 ccerts 权限的用户身份运行 keytool:

keytool -import -file <the cert file> -alias <some meaningful name> -keystore <path to cacerts file>

它很可能会要求你输入密码。Java 提供的默认密码是 changeit。几乎没有人改变它。完成这些相对简单的步骤之后,您就可以安全地与正确的服务器进行通信,并确保您正在与正确的服务器进行通信(只要它们没有丢失私钥)。

Whenever we are trying to connect to URL,

如果其他站点的服务器运行的是 https 协议,并要求我们通过证书中提供的信息进行通信,那么 我们有以下选择:

1)请求证书(下载证书) ,在信托中导入该证书。默认的 Java 信任使用可以在 Javajdk1.6.0 _ 29 jre lib 安全性 ccerts 中找到,那么如果我们重新尝试连接到 URL 连接将被接受。

2)在正常的业务案例中,我们可能连接到组织内部的 URLS,我们知道它们是正确的。 在这种情况下,您相信它是正确的 URL,在这种情况下,可以使用代码,不会强制存储证书连接到特定的 URL。

关于第2点,我们必须遵循以下步骤:

1)写下设置 HttpsURLConnection 的 HostnameVerifier 的方法,该方法在所有情况下返回 true,这意味着我们信任信任存储。

  // trusting all certificate
public void doTrustToCertificates() throws Exception {
Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}


public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
return;
}


public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {
return;
}
}
};


SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HostnameVerifier hv = new HostnameVerifier() {
public boolean verify(String urlHostName, SSLSession session) {
if (!urlHostName.equalsIgnoreCase(session.getPeerHost())) {
System.out.println("Warning: URL host '" + urlHostName + "' is different to SSLSession host '" + session.getPeerHost() + "'.");
}
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(hv);
}

2)写下面的方法,该方法在尝试连接到 URL 之前调用 doTrustToSecurities

    // connecting to URL
public void connectToUrl(){
doTrustToCertificates();//
URL url = new URL("https://www.example.com");
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
System.out.println("ResponseCode ="+conn.getResponseCode());
}

这个调用将返回响应代码 = 200表示连接成功。

有关更多细节和示例,请参阅 网址

可以通过两种方式解决 SSLHandshakeException。

  1. 加入 SSL

    • 获取 SSL (通过询问源代码系统管理员,也可以 命令下载,或者任何浏览器下载 证书)

    • 将证书添加到位于 JRE/lib/security

    • 在 vm 参数中提供信任库位置 “-Djavax.net.ssl.trust Store =”

  2. 忽略 SSL

    关于这个 # 2,请访问我在另一个 stackoverflow 网站上的其他答案: 如何忽略 SSL 验证 使用 Java 忽略 SSL 证书错误

这是我使用最新的 JDK 11 HttpClient 将 JSON 发布到具有不安全/无效 SSL 证书的 URL 时所做的事情:

    // Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
}
};


try {


// Install the all-trusting trust manager
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());


// Creat HttpClient with new SSLContext.
HttpClient httpClient = HttpClient.newBuilder()
.connectTimeout(Duration.ofMillis(3 * 1000))
.sslContext(sc) // SSL context 'sc' initialised as earlier
.build();


// Create request.
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(<URL>))
.timeout(Duration.ofMinutes(1))
.header("Content-Type", "application/json")
.header("Accept", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(<PAYLOAD JSON STRING>))
.build();


//Send Request
HttpResponse<String> response =
httpClient.send(request, HttpResponse.BodyHandlers.ofString());


//Access response JSON
String responseJson = response.body();


} catch (Exception e) {
throw new Exception(e);
}