解决 javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path buildin

Posted

技术标签:

【中文标题】解决 javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed 错误?【英文标题】:Resolving javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed Error? 【发布时间】:2012-03-26 00:24:21 【问题描述】:

编辑:我尝试在blog 中以更形象的方式格式化问题并接受答案。

这是原始问题。

我收到此错误:

详细消息 sun.security.validator.ValidatorException: PKIX 路径 构建失败: sun.security.provider.certpath.SunCertPathBuilderException:无法 找到请求目标的有效认证路径

导致 javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException:PKIX 路径构建 失败:sun.security.provider.certpath.SunCertPathBuilderException: 无法找到请求目标的有效认证路径

我使用 Tomcat 6 作为网络服务器。我在不同端口上的不同 Tomcat 上安装了两个 HTTPS Web 应用程序,但在同一台机器上。说 App1(端口 8443)和 App2(端口 443)。 App1 连接到 App2。当 App1 连接到 App2 时,出现上述错误。我知道这是一个非常常见的错误,因此在不同的论坛和网站上遇到了许多解决方案。我在两个 Tomcat 的 server.xml 中有以下条目:

keystoreFile="c:/.keystore" 
keystorePass="changeit"

每个站点都说app2提供的证书不在app1 jvm的受信任存储中的相同原因。当我试图在 IE 浏览器中点击相同的 URL 时,这似乎也是如此,它可以工作(随着变暖,这个网站的安全证书有问题。这里我说继续这个网站)。但是,当 Java 客户端(在我的情况下)点击相同的 URL 时,我得到了上述错误。因此,为了将其放入信任库,我尝试了以下三个选项:

选项 1

System.setProperty("javax.net.ssl.trustStore", "C:/.keystore");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");

选项 2

在环境变量中设置如下

CATALINA_OPTS -- param name
-Djavax.net.ssl.trustStore=C:\.keystore -Djavax.net.ssl.trustStorePassword=changeit ---param value

选项 3

在环境变量中设置如下

JAVA_OPTS -- param name
-Djavax.net.ssl.trustStore=C:\.keystore -Djavax.net.ssl.trustStorePassword=changeit ---param value

结果

但没有任何效果。

最终起作用的是执行 Pascal Thivent 在How to handle invalid SSL certificates with Apache HttpClient? 中建议的 Java 方法,即执行程序 InstallCert。

但这种方法适用于 devbox 设置,但我无法在生产环境中使用它。

当我在 App2 服务器的server.xml 中提到相同的值并通过设置在信任库中提到相同的值时,我想知道为什么上面提到的三种方法不起作用

System.setProperty("javax.net.ssl.trustStore", "C:/.keystore") and System.setProperty("javax.net.ssl.trustStorePassword", "changeit");

在 App1 程序中。

有关更多信息,这是我建立连接的方式:

URL url = new URL(urlStr);

URLConnection conn = url.openConnection();

if (conn instanceof HttpsURLConnection) 

  HttpsURLConnection conn1 = (HttpsURLConnection) url.openConnection();
  
  conn1.setHostnameVerifier(new HostnameVerifier() 
    public boolean verify(String hostname, SSLSession session) 
      return true;
    
  );

  reply.load(conn1.getInputStream());

【问题讨论】:

HttpClient and SSL的可能重复 奇怪的是,我在单独没有 SSL 问题的集群服务器之间进行通信时遇到了这个错误。一旦我在我的 RHEL 服务器中正确设置了domainname,问题就消失了。希望它可以帮助某人。 要检查的另一件事是您是否拥有最新版本的 Java - 因此我遇到了类似的错误。 ***.com/questions/2893819/… - 也很相关,也是一个很棒的答案。 首先将您的crt文件导入JAVA_HOME/jre/security/cacerts,如果您仍然遇到此异常,请更改您的jdk版本。例如从 jdk1.8.0_17 到 jdk1.8.0_231 【参考方案1】:

您需要将 App2 的证书添加到位于 $JAVA_HOME\lib\security\cacerts 的所用 JVM 的信任库文件中。

首先,您可以通过运行以下命令检查您的证书是否已在信任库中: keytool -list -keystore "$JAVA_HOME/jre/lib/security/cacerts"(无需提供密码)

如果您的证书丢失,您可以使用浏览器下载它并使用以下命令将其添加到信任库:

keytool -import -noprompt -trustcacerts -alias <AliasName> -file   <certificate> -keystore <KeystoreFile> -storepass <Password>

示例:

keytool -import -noprompt -trustcacerts -alias myFancyAlias -file /path/to/my/cert/myCert.cer -keystore /path/to/my/jdk/jre/lib/security/cacerts/keystore.jks -storepass changeit

导入后,您可以再次运行第一个命令以检查您的证书是否已添加。

可以在here找到Sun/Oracle信息。

【讨论】:

您必须使用完整路径,例如c:\java\jdk\lib\security\cacerts 就像 SimonSez 说的,你不需要密码,但如果你想要,默认密码是“changeit”。 另外,在 Windows 中,您需要以管理员身份运行终端,否则在尝试导入证书时会收到错误 keytool error: java.io.FileNotFoundException ... (Access is denied) 啊@SimonSez 你是我的上帝。但要添加它,必须指定@M Sach 提到的信任存储位置和密码才能使其工作。 继续遇到 Java 1.8 的问题。需要按照描述添加证书并使用 Java 【参考方案2】:

javax.net.ssl.SSLHandshakeException:sun.security.validator.ValidatorException:PKIX 路径构建失败:sun.security.provider.certpath.SunCertPathBuilderException:无法找到请求目标的有效证书路径

• 当我收到错误时,我尝试用 Google 搜索出表达式的含义,我发现,当服务器更改其 HTTPS SSL 证书时会出现此问题,并且我们的旧版本 java 无法识别根证书颁发机构(加利福尼亚州)。

• 如果您可以在浏览器中访问 HTTPS URL,则可以更新 Java 以识别根 CA。

• 在您的浏览器中,转到 Java 无法访问的 HTTPS URL。点击HTTPS证书链(Internet Explorer中有锁图标),点击锁查看证书。

• 转到证书的“详细信息”和“复制到文件”。以 Base64 (.cer) 格式复制它。它将保存在您的桌面上。

• 安装证书忽略所有警报。

• 这就是我收集我尝试访问的 URL 的证书信息的方式。

现在我必须让我的 java 版本知道证书,这样它就不会拒绝识别 URL。在这方面我必须提到,我搜索到根证书信息默认保留在 JDK 的 \jre\lib\security 位置,并且访问的默认密码是:changeit.

要查看 cacerts 信息,请遵循以下步骤:

• 点击开始按钮-->运行

• 键入 cmd。命令提示符打开(您可能需要以管理员身份打开它)。

• 转到您的Java/jreX/bin 目录

• 键入以下内容

keytool -list -keystore D:\Java\jdk1.5.0_12\jre\lib\security\cacerts

它给出了包含在密钥库中的当前证书的列表。它看起来像这样:

C:\Documents and Settings\NeelanjanaG>keytool -list -keystore D:\Java\jdk1.5.0_12\jre\lib\security\cacerts

Enter keystore password:  changeit

Keystore type: jks

Keystore provider: SUN

Your keystore contains 44 entries

verisignclass3g2ca, Mar 26, 2004, trustedCertEntry,

Certificate fingerprint (MD5): A2:33:9B:4C:74:78:73:D4:6C:E7:C1:F3:8D:CB:5C:E9

entrustclientca, Jan 9, 2003, trustedCertEntry,

Certificate fingerprint (MD5): 0C:41:2F:13:5B:A0:54:F5:96:66:2D:7E:CD:0E:03:F4

thawtepersonalbasicca, Feb 13, 1999, trustedCertEntry,

Certificate fingerprint (MD5): E6:0B:D2:C9:CA:2D:88:DB:1A:71:0E:4B:78:EB:02:41

addtrustclass1ca, May 1, 2006, trustedCertEntry,

Certificate fingerprint (MD5): 1E:42:95:02:33:92:6B:B9:5F:C0:7F:DA:D6:B2:4B:FC

verisignclass2g3ca, Mar 26, 2004, trustedCertEntry,

Certificate fingerprint (MD5): F8:BE:C4:63:22:C9:A8:46:74:8B:B8:1D:1E:4A:2B:F6

• 现在我必须将之前安装的证书包含到 cacerts 中。

• 为此,过程如下:

keytool -import -noprompt -trustcacerts -alias ALIASNAME -file FILENAME_OF_THE_INSTALLED_CERTIFICATE -keystore PATH_TO_CACERTS_FILE -storepass PASSWORD

如果您使用的是 Java 7:

keytool -importcert -trustcacerts -alias ALIASNAME -file PATH_TO_FILENAME_OF_THE_INSTALLED_CERTIFICATE -keystore PATH_TO_CACERTS_FILE -storepass changeit

• 然后它将证书信息添加到 cacert 文件中。

这是我为上面提到的异常找到的解决方案!

【讨论】:

证书过期了怎么办?重复所有内容(每年)? 有没有办法以编程方式做到这一点? 对于处理 PKIX 错误“路径不与任何信任锚链接”的人来说,不幸的是,这个解决方案并没有解决这个问题。 一个问题 - aliasName 是我们为其导入证书的网址吗?例如,如果 URL 是 domain.site.com/pages/service.asmx,那么别名应该是 domain.site.com 或完整的 URL(domain.site.com/pages/service.asmx) 或者它也应该以 http:// 为前缀,或者它只是一个任意名称? path:\lib\security> keytool -import -noprompt -trustcacerts -alias webCert -file webCertResource.cer -keystore c:/Users/Jackie/Desktop -storepass changeit 我得到“系统找不到指定的文件”【参考方案3】:

我写了一个小的 win32(WinXP 32 位 testet)愚蠢的 cmd(命令行)脚本,它在程序文件中查找所有 java 版本并为它们添加一个证书。 密码需要是默认的“changeit”或在脚本中自己更改:-)

@echo off

for /F  %%d in ('dir /B %ProgramFiles%\java') do (
    %ProgramFiles%\Java\%%d\bin\keytool.exe -import -noprompt -trustcacerts -file some-exported-cert-saved-as.crt -keystore %ProgramFiles%\Java\%%d\lib\security\cacerts -storepass changeit
)

pause

【讨论】:

【参考方案4】:

我的 cacerts 文件完全是空的。我通过将 cacerts 文件从我的 Windows 机器(使用 Oracle Java 7)复制并将其 scp'd 到我的 Linux 机器(OpenJDK)来解决了这个问题。

cd %JAVA_HOME%/jre/lib/security/
scp cacerts mylinuxmachin:/tmp

然后在linux机器上

cp /tmp/cacerts /etc/ssl/certs/java/cacerts

到目前为止效果很好。

【讨论】:

如果问题是您使用的是没有最新证书的较旧版本的 java,这将非常有用。 @atripathi Mac 怎么样? 如果 cacerts 文件为空,则您的 Java 安装存在严重错误。你应该重新安装它。 也许,但这个解决方案奏效了,之后就没有任何问题了。【参考方案5】:

对于在 Ubuntu 服务器上运行的 Tomcat,要找出正在使用的 Java,请使用“ps -ef | grep tomcat”命令:

示例:

/home/mcp01$ **ps -ef |grep tomcat**
tomcat7  28477     1  0 10:59 ?        00:00:18 **/usr/local/java/jdk1.7.0_15/bin/java** -Djava.util.logging.config.file=/var/lib/tomcat7/conf/logging.properties -Djava.awt.headless=true -Xmx512m -XX:+UseConcMarkSweepGC -Djava.net.preferIPv4Stack=true -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=/usr/share/tomcat7/endorsed -classpath /usr/share/tomcat7/bin/bootstrap.jar:/usr/share/tomcat7/bin/tomcat-juli.jar -Dcatalina.base=/var/lib/tomcat7 -Dcatalina.home=/usr/share/tomcat7 -Djava.io.tmpdir=/tmp/tomcat7-tomcat7-tmp org.apache.catalina.startup.Bootstrap start
1005     28567 28131  0 11:34 pts/1    00:00:00 grep --color=auto tomcat

然后,我们可以进入:cd /usr/local/java/jdk1.7.0_15/jre/lib/security

默认 cacerts 文件位于此处。将不受信任的证书插入其中。

【讨论】:

【参考方案6】:

如何在 Tomcat 7 中工作

我想在 Tomcat 应用程序中支持自签名证书,但 以下 sn-p 无法正常工作

import java.io.DataOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class HTTPSPlayground 
    public static void main(String[] args) throws Exception 

        URL url = new URL("https:// ... .com");
        HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();

        httpURLConnection.setRequestMethod("POST");
        httpURLConnection.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
        httpURLConnection.setDoOutput(true);
        DataOutputStream wr = new DataOutputStream(httpURLConnection.getOutputStream());

        String serializedMessage = "";
        wr.writeBytes(serializedMessage);
        wr.flush();
        wr.close();

        int responseCode = httpURLConnection.getResponseCode();
        System.out.println(responseCode);
    

这就是解决我的问题的方法:

1) 下载.crt 文件

echo -n | openssl s_client -connect <your domain>:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ~/<your domain>.crt
&lt;your domain&gt; 替换为您的域(例如jossef.com

2) 在 Java 的 cacerts 证书存储中应用 .crt 文件

keytool -import -v -trustcacerts -alias <your domain> -file ~/<your domain>.crt -keystore <JAVA HOME>/jre/lib/security/cacerts -keypass changeit -storepass changeit
&lt;your domain&gt; 替换为您的域(例如jossef.com) 用您的 java 主目录替换 &lt;JAVA HOME&gt;

3) 破解它

即使我在Java 的默认证书存储中安装了我的证书,Tomcat 也会忽略这一点(似乎它没有配置为使用 Java 的默认证书存储)。

要破解此问题,请在代码中的某处添加以下内容:

String certificatesTrustStorePath = "<JAVA HOME>/jre/lib/security/cacerts";
System.setProperty("javax.net.ssl.trustStore", certificatesTrustStorePath);

// ...

【讨论】:

第 2 步使用 SpringBoot 和 Tomcat 7 为我解决了问题。谢谢。 我必须使用tomcat使用的java中的keytool吗?因为在一台服务器上我可以有很多java @vikifor 是的。您还可以为系统上安装的所有 java 目录运行它 这行得通!非常感谢@JossefHarush 提供如此有用的答案! 在我的代码中添加@Jossef Harush 的代码段后,我的问题得到了解决。【参考方案7】:

我也有这个问题。

我尝试了几乎所有方法,将 SSL 证书添加到 .keystore,但它不适用于 Java1_6_x。 对我来说,如果我们开始使用较新版本的 Java,Java1_8_x 作为 JVM,它会有所帮助。

【讨论】:

对我来说也一样。从 Java 1.8.0_91 到 1.8.0_121 的更新解决了这个问题。我使用 Apache HTTPClient 得到了异常。 我在使用 Oauth2 身份验证时仍然遇到这个问题【参考方案8】:

在 Linux 下使用 Tomcat 7,这成功了。

String certificatesTrustStorePath = "/etc/alternatives/jre/lib/security/cacerts";
System.setProperty("javax.net.ssl.trustStore", certificatesTrustStorePath);
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");

在 Linux 下,$JAVA_HOME 并不总是设置,但通常/etc/alternatives/jre 指向$JAVA_HOME/jre

【讨论】:

【参考方案9】:

对我来说,在尝试连接到处理 SSL 的 nginx 反向代理后面的进程时也会出现此错误。

原来问题在于没有连接整个证书链的证书。 当我添加中间证书时,问题就解决了。

希望这会有所帮助。

【讨论】:

这看起来就像我所拥有的。你能解释一下你是如何添加中间证书的以及在哪里添加的。我使用的是 httpd 反向代理而不是 NGINX。 这对我有帮助,因为我使用 httpd:access.redhat.com/solutions/43575 使用 nginx,它只使用 .key 和 .pem 文件进行 SSL 配置。首先将 .crt 转换为 .pem(简单地说:cp yourfile.crt yourfile.pem),然后对于 SSL 证书链:将 .cer 文件附加到 .pem 的最后(cat yourfile.cer >> yourfile.pem) 【参考方案10】:

另一个原因可能是 JDK 版本过时。我使用的是 jdk 版本 1.8.0_60,只需更新到最新版本即可解决证书问题。

【讨论】:

我也遇到了同样的问题。使用 Lets Encrypt 证书调用 API 可能不适用于旧版本的 Java,因为受信任的根证书颁发机构无法识别它。更新 Java 将解决此问题。【参考方案11】:

可以通过编程方式禁用 SSL 验证。适合开发人员使用,但不推荐用于生产环境,因为您需要在那里使用“真实”SSL 验证,或者安装并使用您自己的受信任密钥,然后仍然使用“真实”SSL 验证。

以下代码对我有用:

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.X509TrustManager;

public class TrustAnyTrustManager implements X509TrustManager 

  public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException 
  

  public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException 
  

  public X509Certificate[] getAcceptedIssuers() 
    return null;
  


             HttpsURLConnection conn = null;
             URL url = new URL(serviceUrl);
             conn = (HttpsURLConnection) url.openConnection();
             SSLContext sc = SSLContext.getInstance("SSL");  
             sc.init(null, new TrustManager[]new TrustAnyTrustManager(), new java.security.SecureRandom());  
                    // Create all-trusting host name verifier
             HostnameVerifier allHostsValid = new HostnameVerifier() 
               public boolean verify(String hostname, SSLSession session) 
                return true;
              
            ;
            conn.setHostnameVerifier(allHostsValid);

或者如果你不控制下面的Connections,你也可以全局覆盖所有连接的SSL验证https://***.com/a/19542614/32453

如果您使用的是 Apache HTTPClient,则必须“以不同方式”(遗憾地)禁用它:https://***.com/a/2703233/32453

【讨论】:

此代码完全不安全,不应使用。 @user207421 为什么它不安全?代码中发生了什么。 这将跳过所有证书验证,基本上它允许接受任何证书。证书的工作方式是在各个认证机构都有一个根证书(字面意思)受到物理保护。然后使用该证书颁发其他二级证书,这些二级证书可以一直验证到根证书颁发机构。这将跳过所有上游检查,这意味着我可以发送任何 ssl 证书(甚至是自己生成的),并且您的应用程序将接受它是安全的,即使我作为 url 的身份没有得到验证。【参考方案12】:

当我遇到同样的问题时,我正在使用jdk1.8.0_171。我在这里尝试了前 2 个解决方案(使用 keytool 添加证书和另一个包含 hack 的解决方案),但它们对我不起作用。

我将我的 JDK 升级到了 1.8.0_181,它就像一个魅力。

【讨论】:

【参考方案13】:

在我的情况下,问题是网络服务器只发送证书和中间 CA,而不是根 CA。 添加这个 JVM 选项解决了这个问题:-Dcom.sun.security.enableAIAcaIssuers=true

支持授权信息访问扩展的 caIssuers 访问方法可用。出于兼容性考虑,默认禁用它,可以通过将系统属性com.sun.security.enableAIAcaIssuers 设置为值 true 来启用它。

如果设置为 true,则 Sun 的 CertPathBuilder 的 PKIX 实现使用证书的 AIA 扩展中的信息(除了指定的 CertStores)来查找颁发的 CA 证书,前提是它是 ldap、http 或 ftp 类型的 URI .

Source

【讨论】:

【参考方案14】:

为了安全,我们不应该在我们的实现中使用自签名证书。但是,在开发方面,我们通常必须使用获得自签名证书的试用环境。我试图在我的代码中以编程方式解决这个问题,但我失败了。但是,通过将证书添加到 jre 信任库解决了我的问题。请找到以下步骤,

    下载网站证书,

    使用Chrome 使用Firefox

    将证书(例如:cert_file.cer)复制到目录$JAVA_HOME\Jre\Lib\Security

    在 Administrator 中打开 CMD 并将目录更改为 $JAVA_HOME\Jre\Lib\Security

    使用以下命令将证书导入信任库,

keytool -import -alias ca -file cert_file.cer -keystore cacerts -storepass changeit

如果您收到错误提示无法识别 keytool,请refer this.

像下面这样输入yes

信任此证书:[是]

    现在尝试运行您的代码或使用 java 以编程方式访问 URL。

更新

如果您的应用服务器是 jboss,请尝试在系统属性下方添加

System.setProperty("org.jboss.security.ignoreHttpsHost","true");

希望这会有所帮助!

【讨论】:

【参考方案15】:

对于 MacOS X,下面是对我有用的确切命令,我不得不在“importcert”选项中尝试使用双连字符,该命令有效:

sudo keytool -–importcert -file /PathTo/YourCertFileDownloadedFromBrowserLockIcon.crt -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/security/cacerts -alias "Cert" -storepass changeit

【讨论】:

【参考方案16】:

当我使用代理时,我在使用 android Studio 时遇到了这个问题。我正在使用 Crashlytics 尝试在构建期间上传映射文件。

我将缺少的代理证书添加到位于的信任库中 /Users/[username]/Documents/Android Studio.app/Contents/jre/jdk/Contents/Home/jre/lib/security/cacerts

使用以下命令:keytool -import -trustcacerts -keystore cacerts -storepass [password] -noprompt -alias [alias] -file [my_certificate_location]

例如使用默认的信任库密码 keytool -import -trustcacerts -keystore cacerts -storepass changeit -noprompt -alias myproxycert -file /Users/myname/Downloads/MyProxy.crt

【讨论】:

【参考方案17】:

在紧要关头,您可以完全禁用 SSL,或按连接禁用(请注意,不建议将其用于生产!)请参阅 https://***.com/a/19542614/32453

【讨论】:

仅代码的答案在本网站上通常不受欢迎。您能否编辑您的答案以包含一些 cmets 或对您的代码的解释?解释应该回答这样的问题:它有什么作用?它是如何做到的?它去哪儿了?它是如何解决OP的问题的? 将此添加到您的代码中不。不要将其添加到您的代码中。以这种方式创建 SSLContext 会删除所有验证您正在连接的服务器身份的安全检查。丢失钥匙问题的答案是从您拥有的所有物品中移除所有锁。【参考方案18】:

对我来说,这个帖子中公认的解决方案没有工作:https://***.com/a/9619478/4507034。

相反,我设法通过将证书导入我的机器受信任证书来解决问题。

步骤:

    转到认证无效的 URL(例如https://localhost:8443/yourpath)。 按照上述帖子中的说明导出认证。 在您的 Windows 机器上打开:Manage computer certificates 转到Trusted Root Certification Authorities -> Certificates 在此处导入您的your_certification_name.cer 文件。

【讨论】:

【参考方案19】:

只是一个小技巧。将文件“hudson.model.UpdateCenter.xml”中的 URL 从 https 更新为 http

<?xml version='1.1' encoding='UTF-8'?>
<sites>
  <site>
    <id>default</id>
    <url>http://updates.jenkins.io/update-center.json</url>
  </site>
</sites>

【讨论】:

【参考方案20】:

可部署的解决方案(Alpine Linux)

为了能够在我们的应用环境中解决这个问题,我们准备了 Linux 终端命令如下:

cd ~

将在主目录中生成证书文件。

apk add openssl

此命令在 alpine Linux 中安装 openssl。您可以找到适用于其他 Linux 发行版的正确命令。

openssl s_client -connect <host-dns-ssl-belongs> < /dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > public.crt

生成了所需的证书文件。

sudo $JAVA_HOME/bin/keytool -import -alias server_name -keystore $JAVA_HOME/lib/security/cacerts -file public.crt -storepass changeit -noprompt

使用程序“keytool”将生成的文件应用到 JRE。

注意:请将您的 DNS 替换为 &lt;host-dns-ssl-belongs&gt;

注意2:请注意-noprompt不会提示验证信息(是/否),-storepass changeit参数将禁用密码提示并提供所需密码(默认为'changeit' )。这两个属性将允许您在应用程序环境中使用这些脚本,例如构建 Docker 映像。

注意3 如果您通过 Docker 部署您的应用程序,您可以生成一次密钥文件并将其放入您的应用程序项目文件中。您无需一次又一次地生成它。

【讨论】:

【参考方案21】:

我想插话,因为我有一个 QEMU 环境,我必须在其中下载 java 文件。事实证明 QEMU 中的 /etc/ssl/certs/java/cacerts 确实有问题,因为它与主机环境中的 /etc/ssl/certs/java/cacerts 不匹配。主机环境位于公司代理之后,因此 java cacerts 是自定义版本。

如果您使用的是 QEMU 环境,请确保主机系统首先可以访问文件。例如,您可以先在主机上尝试this script 以查看。如果脚本在主机上运行得很好,但在 QEMU 中却没有,那么你和我有同样的问题。

为了解决这个问题,我不得不把QEMU中的原文件备份,将宿主环境中的文件复制到QEMU chroot jail,然后java就可以在QEMU中正常下载文件了。

更好的解决方案是将/etc 挂载到QEMU 环境中;但是我不确定其他文件是否会在此过程中受到影响。所以我决定使用这个丑陋但简单的解决方法。

【讨论】:

【参考方案22】:

这似乎是记录臭名昭著的 PKIX 错误消息的另一个可能原因的好地方。在查看密钥库和信任库内容以及各种 java 安装配置太久之后,我意识到我的问题归结为......一个错字。

错字意味着我也使用密钥库作为信任库。由于我的公司根 CA 没有被定义为密钥库中的独立证书,而只是作为证书链的一部分,并且没有在其他任何地方定义(即 cacerts),所以我不断收到 PKIX 错误。

在发布失败(这是 prod 配置,其他地方没问题)和两天的挠头后,我终于看到了错字,现在一切都很好。

希望这对某人有所帮助。

【讨论】:

【参考方案23】:

我的两分钱: 就我而言, cacerts 不是文件夹,而是文件,而且它存在于两条路径上 发现后,将.jks文件复制到该文件后,错误消失了。

# locate cacerts    
/usr/java/jdk1.8.0_221-amd64/jre/lib/security/cacerts
/usr/java/jre1.8.0_221-amd64/lib/security/cacerts

备份后,我将 .jks 复制过来。

cp /path_of_jks_file/file.jks /usr/java/jdk1.8.0_221-amd64/jre/lib/security/cacerts
cp /path_of_jks_file/file.jks /usr/java/jre1.8.0_221-amd64/lib/security/cacerts

注意:这个基本技巧解决了 Genexus 项目上的这个错误,尽管 file.jks 也在 Tomcat 的 server.xml 文件中。

【讨论】:

【参考方案24】: 确保您的 JVM 位置。可以有六个 JRE 你的系统。您的 Tomcat 真正使用的是哪一个?里面的任何地方 在 Tomcat 中运行的代码,编写 println(System.getProperty("java.home"))。注意这个位置。在 /lib/security/cacerts 文件是使用的证书 你的 Tomcat。 查找失败的根证书。这可以是 通过使用 -Djavax.net.debug=all 打开 SSL 调试发现。运行你的 来自控制台 ssl 的 app 和 note 记录失败的 CA。它的网址 将可用。就我而言,我惊讶地发现代理 zscaler 是失败的,因为它实际上是在代理我的调用,并返回它自己的 CA 证书。 在浏览器中粘贴网址。证书将获得 已下载。 使用 keytool import 将此证书导入 cacerts。

【讨论】:

【参考方案25】:

我在从运行在 AWS EC2 中的应用服务器进行 REST 调用时遇到了这个问题。以下步骤为我解决了这个问题。

    curl -vs https://your_rest_path 回声 | openssl s_client -connect your_domain:443 sudo apt-get install ca-certificates

curl -vs https://your_rest_path 现在可以工作了!

【讨论】:

【参考方案26】:

我在 Apache Tomcat/7.0.67 和 Java JVM 版本:1.8.0_66-b18 上也有同样的问题。随着 Java 升级到 JRE 1.8.0_241,问题似乎解决了。

【讨论】:

【参考方案27】:

如果您使用的是 JDK 11,则该文件夹中不再包含 JRE。证书的位置是 jdk-11.0.11/lib/security/cacerts。

【讨论】:

【参考方案28】:

我正在使用颤振并突然收到此错误。所以,基本上发生的是android/build.gradle 文件中的依赖项中的行,例如:

  classpath 'com.android.tools.build:gradle:4.1.0'
  classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

要求成绩文件从 Internet 下载的认证。但是当有东西阻止 gradle 下载这些证书时,通常会显示出来。

我尝试导出证书并手动添加它,但它似乎对我不起作用。在无数次挠头之后,对我有用的是从您的网络偏好中禁用代理。有人提到禁用 Charles Proxy 会修复它,但在那一刻,我不知道 Charles 是什么,代理是什么。在我的情况下,我没有 Charles 代理,所以我继续在 Mac 的网络首选项设置中查找代理(它可以在 Windows 的网络设置中的某处找到)。我在代理中启用了 Socks。我禁用了它,然后再次重建了 gradle 和 TA-DAH !!!效果很好。

有几件事要记住。如果您在禁用代理后立即构建项目而不关闭网络首选项选项卡,则禁用代理将不起作用,并且会显示相同的错误。此外,如果您已经构建了项目并且在禁用代理后再次运行它,那么它很可能会显示相同的错误(可能是由于 IDE 缓存)。它对我的工作原理:重新启动 Mac,在浏览器中打开几个选项卡(用于一些网络调用),从系统首选项>> wifi 中检查网络首选项并禁用代理,关闭系统首选项应用程序,然后构建项目。

【讨论】:

【参考方案29】:

留意@NDeveloper 的精彩回答。我当然做了复制粘贴,改变了值,我得到了

Illegal option:  ?import

我确实检查了连字符,我看到那个答案是使用 ASCII 的连字符

– 8211

如果您遇到问题,请检查对我有用的 ASCII 代码是这个代码 = 45

- 45

我的代码

keytool -import -noprompt -trustcacerts -alias Certificado -file "C:\Users\JavIut\Desktop\Company\Certificados\Certificado.cer" -keystore "C:\Program Files\Java\jdk1.8.0_121\jre\lib\security\cacerts"

【讨论】:

【参考方案30】:

对于 OkHttpClient,这个解决方案对我有用。 它可能会帮助使用该库的人...

try 

            String proxyHost = "proxy_host";
            String proxyUsername = "proxy_username";
            String proxyPassword = "proxy_password";

            Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, "port goes here"));

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

            // Install the all-trusting trust manager
            final SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
            // Create an ssl socket factory with our all-trusting manager
            final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

            OkHttpClient client = new OkHttpClient().newBuilder()
                    .sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0])
                    .hostnameVerifier((hostname, session) -> true)
                    .connectTimeout(timeout, TimeUnit.SECONDS)
                    .proxy(proxy)
                    .proxyAuthenticator((route, response) -> 
                        String credential = Credentials.basic(proxyUsername, proxyPassword);
                        return response.request().newBuilder()
                                .header("Proxy-Authorization", credential)
                                .build();
                    )
                    .build();

            MediaType mediaType = MediaType.parse("application/json");
            RequestBody requestBody = RequestBody.create(payload, mediaType);

            Request request = new Request.Builder()
                    .url(url)
                    .header("Authorization", "authorization data goes here")
                    .method(requestMethod, requestBody)
                    .build();

            Response response = client.newCall(request).execute();

            resBody = response.body().string();

            int responseCode = response.code();

         catch (Exception ex) 
        

【讨论】:

以上是关于解决 javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path buildin的主要内容,如果未能解决你的问题,请参考以下文章

VS2005中的生成解决方案, 清理解决方案是啥意思?

云原生景观:可观察性和分析解决了什么问题?如何解决的?

vs2008解决方案资源管理器不显示解决方案

什么是 沙盒解决方案

解决PowerShell乱码问题

如何解决解决方案中现有项目的c#CS0006错误