修复 错误 Javax.Net.SSL.SSLHandshakeException
本篇文章介绍了 Java 中的 javax.net.ssl.SSLHandshakeException
错误。
Java 中的 SSL 握手
SSL 握手用于客户端和服务器建立安全连接所需的信任和后勤保障。 SSL 握手操作需要遵循以下典型步骤:
- 首先,客户端将提供所有可能的密码套件和 SSL 版本的列表。
- 然后,服务器将就特定的密码套件和 SSL 版本达成一致,并以证书进行响应。
- 然后,客户端将从给定证书中提取公钥并使用新的加密预主密钥进行响应。
- 然后,服务器将使用私钥来解密预主密钥。
- 然后,客户端和服务器将使用预主密钥一起计算共享密钥。
- 最后,客户端和服务器将交换消息,确认共享密钥的加密和解密成功。
SSL 握手有两种类型。 第一种是单向 SSL,它让服务器信任所有客户端;第二种是双向 SSL,其中客户端和服务器必须接受彼此的证书。
了解了 SSL 握手之后,我们现在可以详细讨论 SSLHandShakeException。 SSLHandShakeException有两种情况,如下所示。
修复由于缺少服务器证书而导致的 SSLHandshakeException
如果客户端连接服务器时的 SSL 握手操作没有收到任何证书,则会抛出 SSLHandShakeException,如下所示:
Exception in thread "main" javax.net.ssl.SSLHandshakeException:
Received fatal alert: handshake_failure
要解决此问题,请确保遵循上述所有步骤。 当密钥库或系统属性输入不正确时,会出现此问题。
Keystore是权威机构提供的证书,或者我们也可以使用JDK的keytool功能来创建我们的Keystore。 以下是密钥库的示例:
$ keytool -genkey -keypass password \
-storepass password \
-keystore Server_Keystore.jks
上面的keytool代码是写在Keystore文件中的。 现在可以使用 keytool 从上面生成的密钥库文件中提取公共证书:
$ keytool -export -storepass password \
-file NewServer.cer \
-keystore Server_Keystore.jks
上面的代码将从密钥库中将公共证书导出为文件 NewServer.cer。 现在,我们可以将其添加到客户端的信任库中:
$ keytool -import -v -trustcacerts \
-file NewServer.cer \
-keypass password \
-storepass password \
-keystore Client_Truststore.jks
现在服务器的密钥库和客户端的信任库已生成。 我们可以使用命令将它们作为系统属性传递给服务器:
-Djavax.net.ssl.keyStore=Client_Keystore.jks -Djavax.net.ssl.keyStorePassword=password
这是系统属性所必需的。 密钥库文件路径必须是绝对路径,或者将密钥库文件放置在调用命令的同一目录中。
不支持相对路径。 一旦遵循此过程,丢失证书错误将得到解决,并且不会再出现 SSLHandShakeException。
修复由于不受信任的服务器证书导致的 SSLHandShakeException
SSLHandShakeException 的另一个原因是服务器证书不受信任。 当服务器使用未经权威机构签名的自签名证书时,它将抛出以下错误:
Exception in thread "main" 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
每当证书由默认存储之外的任何实体签名时,都会引发此异常。 JDK 中的默认信任库提供有关正在使用的常见证书的信息。
这个问题可以通过强制客户端信任服务器提供的证书来解决。 我们需要使用上面生成的信任库并将它们作为系统属性传递给客户端:
-Djavax.net.ssl.trustStore=Client_Truststore.jks -Djavax.net.ssl.trustStorePassword=password
这将解决异常,但这不是理想的情况。 在理想情况下,我们可以使用自签名证书,该证书应该由证书颁发机构(CA)认证,然后客户端可以默认信任它们。
修复因证书错误导致的 SSLHandShakeException
由于证书不正确,握手也可能失败。 当证书未正确创建时,会抛出 SSLHandShakeException:
Exception in thread "main" javax.net.ssl.SSLHandshakeException:
java.security.cert.CertificateException:
No name matching localhost found
要检查证书是否已正确创建,请运行以下命令:
keytool -v -list -keystore Server_Keystore.jks
上面的命令将显示密钥库所有者的详细信息:
...
Owner: CN=localhost, OU=technology, O=delftstack, L=city, ST=state, C=xx
..
所有者的 CN 必须与服务器的 CN 匹配,如果不匹配,则会抛出与上面所示的相同的异常,因为它是由于 CN 不同而生成的。
修复 SSL 版本和密码套件不兼容导致的 SSLHandShakeException
在 SSL 握手操作时,可能会存在各种加密协议,例如不同版本的 SSL、TLS 等。虽然客户端和服务器必须在握手时就加密协议和版本达成一致,但 SSL 会被 TLS 取代 它的加密强度。
现在,例如,如果服务器使用协议 SSL3,而客户端使用协议 TLS1.3,则双方无法就加密协议达成一致,并且会抛出 SSLHandShakeException:
Exception in thread "main" javax.net.ssl.SSLHandshakeException:
No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
为了解决这个问题,我们必须验证客户端和服务器是否使用相同或兼容的加密协议。
同样,也需要有兼容的密码套件。 握手时,客户端提供密码列表,服务器将选择要使用的密码。
如果服务器无法选择合适的密码,代码将抛出以下 SSLHandShakeException:
Exception in thread "main" javax.net.ssl.SSLHandshakeException:
Received fatal alert: handshake_failure
通常客户端和服务器端使用多种密码套件; 这就是发生此错误的原因。 发生该错误的原因是服务器选择了选择性很强的密码。
为了避免这个问题,服务器使用选择性密码列表,这也有利于安全。
相关文章
如何在 Java 中延迟几秒钟的时间
发布时间:2023/12/17 浏览次数:217 分类:Java
-
本篇文章主要介绍如何在 Java 中制造程序延迟。本教程介绍了如何在 Java 中制造程序延时,并列举了一些示例代码来了解它。
如何在 Java 中把 Hashmap 转换为 JSON 对象
发布时间:2023/12/17 浏览次数:187 分类:Java
-
它描述了允许我们将哈希图转换为简单的 JSON 对象的方法。本文介绍了在 Java 中把 Hashmap 转换为 JSON 对象的方法。我们将看到关于创建一个 hashmap,然后将其转换为 JSON 对象的详细例子。
如何在 Java 中按值排序 Map
发布时间:2023/12/17 浏览次数:171 分类:Java
-
本文介绍了如何在 Java 中按值对 Map 进行排序。本教程介绍了如何在 Java 中按值对 Map
进行排序,并列出了一些示例代码来理解它。
如何在 Java 中打印 HashMap
发布时间:2023/12/17 浏览次数:192 分类:Java
-
本帖介绍了如何在 Java 中打印 HashMap。本教程介绍了如何在 Java 中打印 HashMap 元素,还列举了一些示例代码来理解这个主题。
在 Java 中更新 Hashmap 的值
发布时间:2023/12/17 浏览次数:146 分类:Java
-
本文介绍了如何在 Java 中更新 HashMap 中的一个值。本文介绍了如何在 Java 中使用 HashMap 类中包含的两个方法-put() 和 replace() 更新 HashMap 中的值。
Java 中的 hashmap 和 map 之间的区别
发布时间:2023/12/17 浏览次数:79 分类:Java
-
本文介绍了 Java 中的 hashmap 和 map 接口之间的区别。本教程介绍了 Java 中 Map 和 HashMap 之间的主要区别。在 Java 中,Map 是用于以键值对存储数据的接口,
在 Java 中获取用户主目录
发布时间:2023/12/17 浏览次数:218 分类:Java
-
这篇文章向你展示了如何在 Java 中获取用户主目录。本教程介绍了如何在 Java 中获取用户主目录,并列出了一些示例代码以指导你完成该主题。
Java 中 size 和 length 的区别
发布时间:2023/12/17 浏览次数:179 分类:Java
-
这篇文章教你如何知道 Java 中大小和长度之间的区别。本教程介绍了 Java 中大小和长度之间的区别。我们还列出了一些示例代码以帮助你理解该主题。
Java 中的互斥锁
发布时间:2023/12/17 浏览次数:111 分类:Java
-
了解有关 Java 中互斥锁的一切,在计算机科学领域,互斥或互斥被称为并发控制的属性。每台计算机都使用称为线程的最小程序指令序列。有一次,计算机在一个线程上工作。为了更好地理解,