development

요청한 대상에 대한 유효한 인증 경로를 찾을 수 없음-인증서를 가져온 후에도 오류

big-blog 2020. 5. 20. 08:20
반응형

요청한 대상에 대한 유효한 인증 경로를 찾을 수 없음-인증서를 가져온 후에도 오류


자체 서명 된 인증서로 서버에 액세스하려고하는 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 파일을 읽지 않고 다른 파일을 읽었 기 때문에 이것이 느낌입니다.

당신 중 누구 에게이 문제가 있고 올바른 방향으로 나를 밀어 줄 수 있습니까?


불행히도 많은 것들이 될 수 있으며 많은 응용 프로그램 서버와 다른 Java '래퍼'가 속성을 가지고 노는 경향이 있으며 '자체'가 키 체인을 취하는 것과 그렇지 않은 것. 완전히 다른 것을보고있을 수 있습니다.

트러스 싱 부족-시도해 보았습니다.

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

그것이 도움이되는지 확인하십시오. 'all'대신에 키 관리자 및 신뢰 관리자 인 'ssl'로 설정할 수도 있습니다. 이는 귀하의 경우에 도움이 될 수 있습니다. 'help'로 설정하면 대부분의 플랫폼에서 다음과 같은 내용이 나열됩니다.

어쨌든-키 저장소 (개인 키와 인증서가있는 신원을 가지고있는)와 신뢰 저장소 (신뢰할 수있는 사람을 결정)와의 차이점과 자신의 신원도 사실을 완전히 이해해야합니다. 루트에 대한 신뢰의 '사슬'을 가지고 있습니다-그것은 당신이 신뢰하는 '누구'를 알아 내기 위해 필요한 어떤 사슬과도 분리됩니다.

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 참조


해결책은 다음과 같습니다. 아래 링크를 단계별로 따르십시오.

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

자바 파일 : 블로그에서 누락

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

}

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 사이트를 참조하십시오 .


sbt 와 같은 문제가있었습니다 . repo1.maven.org 에서 ssl을 통해
종속성을 가져 오려고 시도했지만 "요청한 대상 URL에 유효한 인증 경로를 찾을 수 없습니다"라고 말했습니다. 그래서 나는 이 게시물을 따라 여전히 연결을 확인하지 못했습니다. 그래서 그것에 대해 읽고 게시물에서 제안한 것처럼 루트 인증서가 충분하지 않다는 것을 알았습니다. 그래서 나를 위해 일한 것은 중간 CA 인증서를 키 저장소로 가져 오는 것입니다 . 실제로 체인에 모든 인증서를 추가했으며 매력처럼 작동했습니다.





(에서 재 게시 내 다른 응답 )
CLI 유틸리티 사용 키 도구를 가져 오기위한 자바 소프트웨어 배포에서 (그리고 신뢰! )에 필요한 인증서

견본:

  1. cli change 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를 사용해야합니다.

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


Solution when migrating from JDK 8 to 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

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

Steps to fix

  • I deleted the JDK 10 cert and replaced it with the JDK 8
  • Since I'm building Docker Images, I could quickly do that using Multi-stage builds
    • I'm building a minimal JRE using jlink as /opt/jdk/bin/jlink \ --module-path /opt/jdk/jmods...

So, here's the different paths and the sequence of the commands...

# 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

My problem was that a Cloud Access Security Broker, NetSkope, was installed on my work laptop through a software update. This was altering the certificate chain and I was still not able to connect to the server through my java client after importing the entire chain to my cacerts keystore. I disabled NetSkope and was able to successfully connect.


I am working on a tutorial for REST web services at www.udemy.com (REST Java Web Services). The example in the tutorial said that in order to have SSL, we must have a folder called "trust_store" in my eclipse "client" project that should contain a "key store" file (we had a "client" project to call the service, and "service" project that contained the REST web service - 2 projects in the same eclipse workspace, one the client, the other the service). To keep things simple, they said to copy "keystore.jks" from the glassfish app server (glassfish\domains\domain1\config\keystore.jks) we are using and put it into this "trust_store" folder that they had me make in the client project. That seems to make sense: the self-signed certs in the server's key_store would correspond to the certs in the client trust_store. Now, doing this, I was getting the error that the original post mentions. I have googled this and read that the error is due to the "keystore.jks" file on the client not containing a trusted/signed certificate, that the certificate it finds is self-signed.

To keep things clear, let me say that as I understand it, the "keystore.jks" contains self-signed certs, and the "cacerts.jks" file contains CA certs (signed by the CA). The "keystore.jks" is the "keystore" and the "cacerts.jks" is the "trust store". As "Bruno", a commenter, says above, "keystore.jks" is local, and "cacerts.jks" is for remote clients.

So, I said to myself, hey, glassfish also has the "cacerts.jks" file, which is glassfish's trust_store file. cacerts.jsk is supposed to contain CA certificates. And apparently I need my trust_store folder to contain a key store file that has at least one CA certificate. So, I tried putting the "cacerts.jks" file in the "trust_store" folder I had made, on my client project, and changing the VM properties to point to "cacerts.jks" instead of "keystore.jks". That got rid of the error. I guess all it needed was a CA cert to work.

This may not be ideal for production, or even for development beyond just getting something to work. For instance you could probably use "keytool" command to add CA certs to the "keystore.jks" file in the client. But anyway hopefully this at least narrows down the possible scenarios that could be going on here to cause the error.

ALSO: my approach seemed to be useful for the client (server cert added to client trust_store), it looks like the comments above to resolve the original post are useful for the server (client cert added to server trust_store). Cheers.

Eclipse project setup:

  • MyClientProject
  • src
  • test
  • JRE System Library
  • ...
  • trust_store
    ---cacerts.jks ---keystore.jks

Snippet from MyClientProject.java file:

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");
        }

  });
}

Check if the file $JAVA_HOME/lib/security/cacerts exists! In my case it was not a file but a link to /etc/ssl/certs/java/cacerts and also this was a link to itself (WHAT???) so due to it JVM can't find the file.

Solution: Copy the real cacerts file (you can do it from another JDK) to /etc/ssl/certs/java/ directory and it'll solve your problem :)


In my case I was facing the problem because in my tomcat process specific keystore was given using

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

Wheras I was importing the certificate to the cacert of JRE/lib/security and the changes were not reflecting. Then I did below command where /tmp/cert1.test contains the certificate of the target server

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

We can double check if the certificate import is successful

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

and see if your taget server is found against alias rapidssl-myserver


Lets say if you are using classpath variables like ${JAVA_HOME} in pom.xml.

<target>
                    <property name="compile_classpath" refid="maven.compile.classpath"/>
                    <property name="runtime_classpath" refid="maven.runtime.classpath"/>
                    <property name="test_classpath" refid="maven.test.classpath"/>
                    <property name="plugin_classpath" refid="maven.plugin.classpath"/>
                    <property name="jaxb-api.jar" value="${maven.dependency.javax.xml.bind.jaxb-api.jar.path}"/>
                    <property name="project_home" value="${PROJECT_HOME}"/>
                    <property name="java_home" value="${JAVA_HOME}"/>
                    <property name="ant_home" value="${ANT_HOME}"/>
                    <property name="common_home" value="${COMMON_HOME}"/>
                    <property name="JAXP_HOME" value="${common_home}/lib"/>
                    <property name="ejfw_home" value="${PROJECT_HOME}/lib"/>
                    <property name="weblogic_home" value="${WL_HOME}"/>
                    <property name="fw_home" value="${FW_HOME}"/>
                    <property name="env" value="${BUILDENV}"/>
                    <property name="tokenfile" value="${BUILDENV}${BUILDENV_S2S}.properties"/>

On goals, add the classpath variables. i.e..., -DANT_HOME , -DJAVA_HOME

clean install -e -DPROJECT_HOME=..... -DANT_HOME=C:\bea1036\modules\org.apache.ant_1.7.1 -DJAVA_HOME=C:\bea1036\jdk160_31

참고URL : https://stackoverflow.com/questions/9210514/unable-to-find-valid-certification-path-to-requested-target-error-even-after-c

반응형