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

The*_*der 182 java ssl keytool

我有一个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并退出了"帖子".

我仍然得到同样的错误.

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

你们有没有遇到过这个问题,能否把我推向正确的方向?

Dir*_*lik 140

不幸的是 - 它可能是很多东西 - 很多应用程序服务器和其他java'包装器'都倾向于使用属性和它们自己的"钥匙链"以及其他内容.所以它可能正在寻找完全不同的东西.

没有桁架 - 我会尝试:

java -Djavax.net.debug=all -Djavax.net.ssl.trustStore=trustStore ...
Run Code Online (Sandbox Code Playgroud)

看看是否有帮助.除了'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
Run Code Online (Sandbox Code Playgroud)

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

  • 非常感谢!-Djavax.net.ssl.trustStore =/location_of/trustStore解决了我的问题,调试信息也非常有用. (5认同)
  • java -Djavax.net.debug = all -Djavax.net.ssl.trustStore = trustStore ...给出以下错误:错误:找不到或加载主类... (4认同)
  • 当然,您可能还需要使用 -Djavax.net.ssl.trustStorePassword=changeit 指定信任库的密码 (2认同)

小智 18

这是解决方案,请按照以下链接逐步进行:

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

JAVA FILE:博客中遗漏了这些内容

/*
 * 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);
    }
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 这个答案主要是代码。它没有解释为什么或为什么不起作用。 (6认同)
  • 这种“解决方案”根本上是不安全的。不使用。 (4认同)
  • 这个解决方案对我有用,但它需要在私有类SavingTrustManager中进行一些小改动:`public X509Certificate [] getAcceptedIssuers(){return new X509Certificate [0];} (3认同)

Vic*_*Vic 12

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

通过命令行:

java -Djavax.net.ssl.trustStore=truststores/client.ts com.progress.Client
Run Code Online (Sandbox Code Playgroud)

或通过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);
    ...
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请参阅RedHat网站上的详细信息.


Deb*_*Deb 10

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
Run Code Online (Sandbox Code Playgroud)

密码: 更改

方法二:

创建信任存储:

keytool -import -alias myCert -file C://certificate.cert -keystore myTrustStore
Run Code Online (Sandbox Code Playgroud)

它会给出以下提示,可以填写为:

Enter keystore password:changeit
Re-enter new password:changeit
Trust this certificate?yes
Run Code Online (Sandbox Code Playgroud)

这将在您运行此命令的文件夹中创建一个myTrustStore文件。将此“mytrustStore”复制到方便的位置。

使用信任存储:

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

-Djavax.net.ssl.trustStore=C://myTrustStore -Djavax.net.ssl.trustStorePassword=changeit
Run Code Online (Sandbox Code Playgroud)


Dan*_*Mor 5

我对sbt有同样的问题。
它试图通过ssl 从repo1.maven.org获取依赖关系,
但表示“无法找到到所请求目标URL的有效证书路径”。
因此我关注了这篇文章 ,但仍然无法验证连接。
所以我读了一下,发现根证书还不够,正如帖子所建议的那样
,对我有用的是将中间CA证书导入密钥库
实际上,我在链中添加了所有证书,它的工作原理就像一个魅力。


Але*_*ный 5

(从我的其他响应中重新发布)
使用来自java软件分发的cli实用程序keytool导入(并且信任!)所需的证书

样品:

  1. 从cli更改dir到jre\bin

  2. 检查密钥库(在jre\bin目录中找到的文件)
    keytool -list -keystore ..\lib\security\cacerts
    密码是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

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


Mar*_*les 5

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

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

修复步骤

  • 我删除了 JDK 10 证书并将其替换为 JDK 8
  • 由于我正在构建 Docker 映像,因此我可以使用多阶段构建快速完成此操作
    • 我正在使用jlinkas构建一个最小的 JRE/opt/jdk/bin/jlink \ --module-path /opt/jdk/jmods...

所以,这是不同的路径和命令的顺序......

# 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
Run Code Online (Sandbox Code Playgroud)