java - 在 Java 中使用证书进行 HTTPS 请求

标签 java ssl https pkcs#12

我想在 Java 中通过 HTTPS 连接调用一些 Web 服务。证书颁发机构给了我一个 PKCS12 文件,但我得到了一个

sun.security.validator.ValidatorException: PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

由于

javax.net.ssl.SSLHandshakeException

这是我正在执行的代码:

System.setProperty("javax.net.ssl.keyStoreType", "JKS");
System.setProperty("javax.net.ssl.keyStore", "path/toto2.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "pwd");
System.setProperty("javax.net.ssl.trustStoreType", "JKS");
System.setProperty("javax.net.ssl.trustStore", "path/toto2.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "pwd");
System.setProperty("proxySet","true") ;
System.setProperty("https.proxyHost", "XXX") ;
System.setProperty("https.proxyPort", "XXX") ;

我首先尝试提供 PKCS12 文件,然后是 JKS,但我遇到了同样的错误。

我尝试了另一种解决方案,使用 curl。所以我从 PKCS12 中提取了证书并且请求成功了。

以下是我用来从 P12 中提取不同文件的命令:

openssl pkcs12 -in file.p12 -nocerts -nodes -out clientcert.key
openssl pkcs12 -in file.p12 -clcerts -nokeys -out clientcert.cer
openssl pkcs12 -in file.p12 -cacerts -nokeys -chain -out cacerts.cer

我在 Java 中使用这些文件的方式有误吗?

最佳答案

PKCS12 通常包含私钥和证书(链)组合,用于验证您的系统,即客户端,这是通过 javax.net.ssl.keyStore*属性。您应该指定类型 PKCS12,尽管某些 Java8 版本(仅!)在您指定 JKS 时可以读取 PKCS12。

它通常不会对服务器进行身份验证,这是 javax.net.ssl.trustStore* 的用途,所以不要在那里使用它。根据服务器的不同,您可能需要也可能不需要不同于 P12 的自定义信任库,也不同于 Java 的默认值。 使用浏览器或其他工具(如 curlkeytool -printcert -sslserver host[:port] 查看服务器使用的证书链 并确定它是否使用公共(public)根 CA,如 Verisign-now-Symantec-now-Digicert 或 GoDaddy,它们已经在 J​​ava 的默认信任库中,或者是“私有(private)”CA 甚至是自签名证书,在这种情况下你应该要么将该证书添加到默认信任库,要么如果您不能或不想修改您的 JVM,请将该证书放入您用作信任库的 keystore 文件中。

PS:ValidatorException 导致 SSLHandshakeException 而不是相反。

关于java - 在 Java 中使用证书进行 HTTPS 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50598468/

相关文章:

android - iOS 允许无效证书,而 android 不允许

c - 基于 epoll 的非阻塞 ssl_read() 陷入循环

git - 自签名 SSL 证书与 Windows Server 2012、Bonobo Git 服务器一起使用

java - 用java加密数据库用户名和密码?

java - 计算 "for loop"中的数字并返回 java 中的平均值、最小值、最大值

java - 密码检查错误

php - SSL 和 session 劫持/固定

java - 无法通过 Spring Boot 调用 https REST 端点

https 流量似乎流向根域而不是子域

java - 如何将键和值存储到 hashmap 中并相应地打印出来?