即使导入证书后也无法找到请求目标的有效证书路径-错误

我有一个Java客户端试图使用自签名证书访问服务器。

当我试图发布到服务器,我得到以下错误:

无法找到请求目标的有效认证路径

在对这个问题做了一些研究之后,我做了以下工作。

  1. 保存我的服务器域名为root.cer文件。

  2. 在我的Glassfish服务器的JRE中,我运行了这个:

    keytool -import -alias example -keystore cacerts -file root.cer
    
  3. 要检查证书已成功添加到我的cacert,我这样做:

    keytool -list -v -keystore cacerts
    

    我可以看到证书是存在的。

  4. 我然后重新启动Glassfish,并重试'post'。

我还是得到同样的错误。

我有一种感觉,这是因为我的Glassfish实际上没有读取我修改过的cacert文件,但可能是其他一些文件。

你们中有人遇到过这样的问题吗,可以帮我找到正确的方向吗?

1190799 次浏览

不幸的是——这可能是很多事情——很多应用服务器和其他java“包装器”都倾向于玩弄属性和他们自己的钥匙链等。所以它可能会看一些完全不同的东西。

少了桁架-我会试试:

java -Djavax.net.debug=all -Djavax.net.ssl.trustStore=trustStore ...

看看这是否有用。除了“all”,还可以将其设置为“ssl”,密钥管理器和信任管理器-这可能对您的情况有帮助。在大多数平台上,将它设置为“帮助”会列出如下内容。

无论如何,一定要确保您完全理解密钥存储库(其中有您用来证明自己身份的私钥和证书)和信任存储库(它决定您信任谁)之间的区别,以及您自己的身份也有一个到根的信任“链”,这与您需要确定您信任“谁”的根的任何链是分开的。

all            turn on all debugging
ssl            turn on ssl debugging


The   following can be used with ssl:
record       enable per-record tracing
handshake    print each handshake message
keygen       print key generation data
session      print session activity
defaultctx   print default SSL initialization
sslctx       print SSLContext tracing
sessioncache print session cache tracing
keymanager   print key manager tracing
trustmanager print trust manager tracing
pluggability print pluggability tracing


handshake debugging can be widened with:
data         hex dump of each handshake message
verbose      verbose handshake message printing


record debugging can be widened with:
plaintext    hex dump of record plaintext
packet       print raw SSL/TLS packets

来源:#参见http://download.oracle.com/javase/1.5.0/docs/guide/security/jsse/JSSERefGuide.html#Debug

您需要配置JSSE系统属性,特别是指向客户端证书存储。

通过命令行:

java -Djavax.net.ssl.trustStore=truststores/client.ts com.progress.Client

或者通过Java代码:

import java.util.Properties;
...
Properties systemProps = System.getProperties();
systemProps.put("javax.net.ssl.keyStorePassword","passwordForKeystore");
systemProps.put("javax.net.ssl.keyStore","pathToKeystore.ks");
systemProps.put("javax.net.ssl.trustStore", "pathToTruststore.ts");
systemProps.put("javax.net.ssl.trustStorePassword","passwordForTrustStore");
System.setProperties(systemProps);
...

有关更多信息,请参阅RedHat网站

这里是解决方案,按照下面的链接一步一步:

http://www.mkyong.com/webservices/jax-ws/suncertpathbuilderexception-unable-to-find-valid-certification-path-to-requested-target/

JAVA文件:博客中缺少的文件

/*
* Copyright 2006 Sun Microsystems, Inc.  All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*   - Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*
*   - Redistributions in binary form must reproduce the above copyright
*     notice, this list of conditions and the following disclaimer in the
*     documentation and/or other materials provided with the distribution.
*
*   - Neither the name of Sun Microsystems nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/






import java.io.*;
import java.net.URL;


import java.security.*;
import java.security.cert.*;


import javax.net.ssl.*;


public class InstallCert {


public static void main(String[] args) throws Exception {
String host;
int port;
char[] passphrase;
if ((args.length == 1) || (args.length == 2)) {
String[] c = args[0].split(":");
host = c[0];
port = (c.length == 1) ? 443 : Integer.parseInt(c[1]);
String p = (args.length == 1) ? "changeit" : args[1];
passphrase = p.toCharArray();
} else {
System.out.println("Usage: java InstallCert <host>[:port] [passphrase]");
return;
}


File file = new File("jssecacerts");
if (file.isFile() == false) {
char SEP = File.separatorChar;
File dir = new File(System.getProperty("java.home") + SEP
+ "lib" + SEP + "security");
file = new File(dir, "jssecacerts");
if (file.isFile() == false) {
file = new File(dir, "cacerts");
}
}
System.out.println("Loading KeyStore " + file + "...");
InputStream in = new FileInputStream(file);
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(in, passphrase);
in.close();


SSLContext context = SSLContext.getInstance("TLS");
TrustManagerFactory tmf =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
X509TrustManager defaultTrustManager = (X509TrustManager)tmf.getTrustManagers()[0];
SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);
context.init(null, new TrustManager[] {tm}, null);
SSLSocketFactory factory = context.getSocketFactory();


System.out.println("Opening connection to " + host + ":" + port + "...");
SSLSocket socket = (SSLSocket)factory.createSocket(host, port);
socket.setSoTimeout(10000);
try {
System.out.println("Starting SSL handshake...");
socket.startHandshake();
socket.close();
System.out.println();
System.out.println("No errors, certificate is already trusted");
} catch (SSLException e) {
System.out.println();
e.printStackTrace(System.out);
}


X509Certificate[] chain = tm.chain;
if (chain == null) {
System.out.println("Could not obtain server certificate chain");
return;
}


BufferedReader reader =
new BufferedReader(new InputStreamReader(System.in));


System.out.println();
System.out.println("Server sent " + chain.length + " certificate(s):");
System.out.println();
MessageDigest sha1 = MessageDigest.getInstance("SHA1");
MessageDigest md5 = MessageDigest.getInstance("MD5");
for (int i = 0; i < chain.length; i++) {
X509Certificate cert = chain[i];
System.out.println
(" " + (i + 1) + " Subject " + cert.getSubjectDN());
System.out.println("   Issuer  " + cert.getIssuerDN());
sha1.update(cert.getEncoded());
System.out.println("   sha1    " + toHexString(sha1.digest()));
md5.update(cert.getEncoded());
System.out.println("   md5     " + toHexString(md5.digest()));
System.out.println();
}


System.out.println("Enter certificate to add to trusted keystore or 'q' to quit: [1]");
String line = reader.readLine().trim();
int k;
try {
k = (line.length() == 0) ? 0 : Integer.parseInt(line) - 1;
} catch (NumberFormatException e) {
System.out.println("KeyStore not changed");
return;
}


X509Certificate cert = chain[k];
String alias = host + "-" + (k + 1);
ks.setCertificateEntry(alias, cert);


OutputStream out = new FileOutputStream("jssecacerts");
ks.store(out, passphrase);
out.close();


System.out.println();
System.out.println(cert);
System.out.println();
System.out.println
("Added certificate to keystore 'jssecacerts' using alias '"
+ alias + "'");
}


private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray();


private static String toHexString(byte[] bytes) {
StringBuilder sb = new StringBuilder(bytes.length * 3);
for (int b : bytes) {
b &= 0xff;
sb.append(HEXDIGITS[b >> 4]);
sb.append(HEXDIGITS[b & 15]);
sb.append(' ');
}
return sb.toString();
}


private static class SavingTrustManager implements X509TrustManager {


private final X509TrustManager tm;
private X509Certificate[] chain;


SavingTrustManager(X509TrustManager tm) {
this.tm = tm;
}


public X509Certificate[] getAcceptedIssuers() {
throw new UnsupportedOperationException();
}


public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
throw new UnsupportedOperationException();
}


public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
this.chain = chain;
tm.checkServerTrusted(chain, authType);
}
}


}

我对sbt有同样的问题 它试图通过ssl
repo1.maven.org获取依赖项 但表示“无法找到请求的目标url的有效认证路径” 所以我遵循这篇文章
.连接失败 所以我读了一下,发现根证书是不够的,正如帖子所建议的,所以-
对我有用的是将中间CA证书导入到密钥库中.
我实际上在链中添加了所有的证书,它就像一个魔法

我的问题是通过软件更新在我的工作笔记本电脑上安装了一个云访问安全代理NetSkope。这正在改变证书链,在将整个链导入到cacerts密钥存储库后,我仍然无法通过java客户端连接到服务器。我禁用了NetSkope,并且能够成功连接。

我正在www.udemy.com (REST Java web服务)上写REST web服务的教程。教程中的示例说,为了拥有SSL,我们必须在eclipse“客户端”项目中有一个名为“trust_store”的文件夹,该文件夹应该包含一个“密钥存储”文件(我们有一个调用服务的“客户端”项目,以及包含REST web服务的“服务”项目——同一个eclipse工作区中的两个项目,一个是客户端,另一个是服务)。为了保持简单,他们建议复制“keystore”。我们正在使用的glassfish应用服务器(glassfish\domains\domain1\config\keystore.jks),并将其放入他们让我在客户端项目中制作的“trust_store”文件夹中。这似乎是有意义的:服务器的key_store中的自签名cert将对应于客户机trust_store中的cert。现在,这样做,我得到了原来的帖子提到的错误。我在谷歌上搜索了一下,了解到这个错误是由于“密钥库”造成的。客户端上的Jks文件不包含受信任/签名证书,它找到的证书是自签名的。

为了让事情更清楚,让我说一下我理解的“密钥库”。“Jks”包含自签名的certs,以及“cacerts. Jks”。“jks”文件中包含CA证书(由CA签名)。“密钥存储库。Jks是“密钥存储库”,cacerts是“cacerts”。Jks”是“信任商店”。正如一位名叫“布鲁诺”的评论者所说,“密钥库。Jks是本地的,cacerts是本地的。Jks”用于远程客户端。

所以,我对自己说,嘿,玻璃鱼也有“仙人掌”。文件,即glassfish的trust_store文件。除。jsk应该包含CA证书。显然,我需要trust_store文件夹包含至少有一个CA证书的密钥存储文件。所以,我试着把cacerts。在我的客户端项目中,我在“trust_store”文件夹中创建了“cacerts. jks”文件,并将虚拟机属性更改为指向“cacerts. jks”。而不是keystore.jks。这样就消除了错误。我想它只需要一个CA证书就可以工作了。

这对于生产来说可能并不理想,甚至对于开发来说也不理想。例如,您可以使用“keytool”命令将CA证书添加到“密钥存储库”中。Jks”文件在客户端。但无论如何,希望这至少能缩小可能导致错误的情况。

另外:我的方法似乎对客户端有用(服务器证书添加到客户端trust_store),看起来上面解决原始帖子的注释对服务器有用(客户端证书添加到服务器trust_store)。欢呼。

Eclipse项目设置:

  • MyClientProject
  • src
  • 测试
  • JRE系统库
  • ...
  • <李> trust_store < br > ——cacerts.jks 李——keystore.jks < / >

MyClientProject.java文件片段:

static {
// Setup the trustStore location and password
System.setProperty("javax.net.ssl.trustStore","trust_store/cacerts.jks");
// comment out below line
System.setProperty("javax.net.ssl.trustStore","trust_store/keystore.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
//System.setProperty("javax.net.debug", "all");


// for localhost testing only
javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(new javax.net.ssl.HostnameVerifier() {
public boolean verify(String hostname, javax.net.ssl.SSLSession sslSession) {
return hostname.equals("localhost");
}


});
}

(repost from 我的另一个回答)
使用cli实用程序keytool从java软件分发导入(和信任!)所需的证书

示例:

  1. 从命令行更改目录到jre\bin

  2. 检查keystore (file found in jre\bin directory)
    Keytool -list -keystore ..除\ lib \安全\
    密码为changeit

  3. 从需要的服务器下载并保存链中的所有证书。

  4. 添加证书(在需要删除“只读”之前;属性文件..\lib\security\cacerts),运行:

    keytool -alias REPLACE_TO_ANY_UNIQ_NAME -import -keystore.使用实例\lib\security\cacerts -file "r:\root.crt"

我偶然发现了这样一个简单的技巧。 其他解决方案需要使用InstallCert.Java和JDK

. JDK

来源:http://www.java-samples.com/showtutorial.php?tutorialid=210

检查文件$JAVA_HOME/lib/security/cacerts是否存在! 在我的情况下,它不是一个文件,而是一个指向/etc/ssl/certs/java/cacerts的链接,而且这是一个指向自身的链接(什么??),因此JVM无法找到该文件

<强>解决方案: 将真正的cacerts文件(你可以从另一个JDK中完成)复制到/etc/ssl/certs/java/目录,它将解决你的问题:)

JDK 8迁移到JDK 10时的解决方案

  • 证书真的不一样
    • JDK 10有80个,而JDK 8有151个
    • 李< / ul > < / >
    • JDK 10最近添加了certs . dll

      JDK 10

      root@c339504909345:/opt/jdk-minimal/jre/lib/security #  keytool -cacerts -list
      Enter keystore password:
      Keystore type: JKS
      Keystore provider: SUN
      
      
      Your keystore contains 80 entries
      

      JDK 8

      root@c39596768075:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/security/cacerts #  keytool -cacerts -list
      Enter keystore password:
      Keystore type: JKS
      Keystore provider: SUN
      
      
      Your keystore contains 151 entries
      

      修复步骤

      • 我删除了JDK 10证书,并将其替换为JDK 8
      • 由于我正在构建Docker图像,我可以使用多阶段构建快速做到这一点
        • 我正在使用jlink构建一个最小的JRE作为<代码>/opt/jdk/bin/jlink \ ——模块路径/ opt / jdk / jmods…< /代码> < /李> 李< / ul > < / >

        这里是不同的路径和命令的顺序…

        # Java 8
        COPY --from=marcellodesales-springboot-builder-jdk8 /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/security/cacerts /etc/ssl/certs/java/cacerts
        
        
        # Java 10
        RUN rm -f /opt/jdk-minimal/jre/lib/security/cacerts
        RUN ln -s /etc/ssl/certs/java/cacerts /opt/jdk-minimal/jre/lib/security/cacerts
        

在我的例子中,我遇到了这个问题,因为在我的tomcat进程中,特定的密钥存储库是使用的

-Djavax.net.ssl.trustStore=/pathtosomeselfsignedstore/truststore.jks

当我将证书导入JRE/lib/security的cacert时,更改没有反映出来。 然后执行以下命令,其中/tmp/cert1。Test包含目标服务器的证书

keytool -import -trustcacerts -keystore /pathtosomeselfsignedstore/truststore.jks -storepass password123 -noprompt -alias rapidssl-myserver -file /tmp/cert1.test

可以再次检查证书导入是否成功

keytool -list -v -keystore /pathtosomeselfsignedstore/truststore.jks

并查看是否在别名rapidssl-myserver中找到您的taget服务器

在我的情况下,我得到错误连接到AWS Gov Postgres RDS。有一个单独的链接GOV RDS CA certs- https://s3.us-gov-west-1.amazonaws.com/rds-downloads/rds-combined-ca-us-gov-bundle.pem

将此pem certs添加到java的cacerts中。您可以使用下面的脚本。

——WINDOWDS步骤

  1. 使用VSCODE编辑器,安装openssl, keytool插件
  2. 在C:/rds-ca目录下创建目录
  3. 将“cacerts”文件和下面的脚本文件-“addCerts.sh”在目录“rd-ca”
  4. 执行以下命令: 4.1 CD /c/rds-ca/ . 李4.2。/ addCerts.sh < / >
  5. 拷贝cacerts到${JAVA_HOME}/jre/lib/security目录下

脚本代码:

#!/usr/bin/env sh


OLDDIR="$PWD"


CACERTS_FILE=cacerts


cd /c/rds-ca


echo "Downloading RDS certificates..."


curl  https://s3.us-gov-west-1.amazonaws.com/rds-downloads/rds-combined-ca-us-gov-bundle.pem > rds-combined-ca-bundle.pem


csplit -sk rds-combined-ca-bundle.pem "/-BEGIN CERTIFICATE-/" "{$(grep -c 'BEGIN CERTIFICATE' rds-combined-ca-bundle.pem | awk '{print $1 - 2}')}"


for CERT in xx*; do
# extract a human-readable alias from the cert
ALIAS=$(openssl x509 -noout -text -in $CERT |
perl -ne 'next unless /Subject:/; s/.*CN=//; print')
echo "importing $ALIAS"
    

keytool -import \
-keystore  $CACERTS_FILE \
-storepass changeit -noprompt \
-alias "$ALIAS" -file $CERT
done


cd "$OLDDIR"
echo "$NEWDIR"


我在试图从使用自签名证书的应用程序访问https url时遇到了这个错误。 他们提供的是一个.cert文件,我不确定把它放在哪里。我解决它的方式如下:

keytool的位置在JDK/bin文件夹下

方法1:添加证书到默认的Java信任库- cacerts:

keytool -import -alias myCert -file C://certificate.cert -keystore C://Program Files//Java//jdk1.8.0_271//jre//lib//security//cacerts

密码:changeit

方法2:

创建信任存储:

keytool -import -alias myCert -file C://certificate.cert -keystore myTrustStore

它会给你以下提示,可以填充为:

Enter keystore password:changeit
Re-enter new password:changeit
Trust this certificate?yes
这将在运行此命令的文件夹中创建myTrustStore文件。 复制这个“mytruststore”;

使用信任存储:

当你运行你的应用程序/服务器时,传递这些JVM参数:

-Djavax.net.ssl.trustStore=C://myTrustStore -Djavax.net.ssl.trustStorePassword=changeit

在这个问题上浪费了很多时间。如果您导入了证书,您可以看到这里列出了它。

keytool -list -v -keystore $JAVA_HOME/lib/security/cacerts

然后创建新的文件,使用以下命令替换SITE_NAME、SITE_PORT、CERTIFICATE_NAME和保存文件的路径。

echo -n | openssl s_client -connect SITE_NAME:SITE_PORT  \
| openssl x509 > /path/to/save/CERTIFICATE_NAME.cert

就我而言,我在Spring中使用Keycloak时遇到了问题。在我用这个命令创建证书并导入到密钥存储库之后,问题就解决了,它可以正常工作

eclipse / Sts用户注意:

因为eclipse使用它自己的JRE,您应该将certs添加到它自己的JRE密钥存储库中。 我有这个问题,直到我添加certs到Sts的JRE

SSL日志:

`javax.net.ssl|DEBUG|1A|restartedMain|2021-12-06 23:04:00.874` IRST|TrustStoreManager.java:113|trustStore is: D:\sts-4.12.0.RELEASE\plugins\org.eclipse.justj.openjdk.hotspot.jre.full.win32.x86_64_16.0.2.v20210721-1149\jre\lib\security\cacerts
This is the full path: "sts-4.12.0.RELEASE\plugins\org.eclipse.justj.openjdk.hotspot.jre.full.win32.x86_64_16.0.2.v20210721-1149\jre\lib\security\cacerts"

我在我的windows 10笔记本电脑上创建了一个ubuntu,当我试图从https://github.com/yahoo/CMAK网站加载CMAK网站下载时遇到了问题。首先,它给出了致命的ssl错误。

openssl s_client -showcerts -servername github.com -connect github.com:443 </dev/null 2>/dev/null | sed -n -e '/BEGIN\ CERTIFICATE/,/END\ CERTIFICATE/ p'  > github-com.pem

并使用以下命令(确保您为ca-cert设置了正确的路径)

cat github-com.pem | sudo tee -a /etc/ssl/certs/ca-certificates.crt

然后使用以下语句(确保cert的路径正确):

git config --global http.sslCAinfo /etc/ssl/certs/ca-certificates.crt

然后我能够下载CMAK,但当我尝试./sbt clean语句时遇到了问题。它给出了一个pkix path错误。原因是我的cacert文件中没有存储我的公司颁发证书。

我已经下载了公司证书(谷歌),并根据本文将下载的证书添加到cacert文件中。在./sbt之前再使用一次sudo update-ca-certificates。这对我很管用。

注意:在执行以上步骤时,您可能需要在root和exit之间切换。

这就是我所做的。

我想在Java 10上开发应用程序,我有Eclipse IDE 2020-06。 证书导入解决方案对我不起作用。 因此,我安装了Java 11 JDK,切换到最新的Eclipse IDE(在Java 11上运行),并通过在Maven POM下添加这些语句来确保源代码仍然可以根据Java 10编译:

    <maven.compiler.target>1.10</maven.compiler.target>
<maven.compiler.source>1.10</maven.compiler.source>
<maven.compiler.release>10</maven.compiler.release>

它就像一个魔法;没有错误。