[java] “PKIX 경로 구축 실패”및“요청한 대상에 대한 유효한 인증 경로를 찾을 수 없습니다”

내 Java 프로젝트에 twitter4j 라이브러리를 사용하여 트윗을 얻으려고합니다 . 첫 번째 실행에서 인증서 sun.security.validator.ValidatorException및에 대한 오류가 발생했습니다 sun.security.provider.certpath.SunCertPathBuilderException. 그런 다음 트위터 인증서를 다음과 같이 추가했습니다.

C:\Program Files\Java\jdk1.7.0_45\jre\lib\security>keytool -importcert -trustcacerts -file PathToCert -alias ca_alias -keystore "C:\Program Files\Java\jdk1.7.0_45\jre\lib\security\cacerts"

그러나 성공하지 못했습니다. 트윗을 얻는 절차는 다음과 같습니다.

public static void main(String[] args) throws TwitterException {
    ConfigurationBuilder cb = new ConfigurationBuilder();
    cb.setDebugEnabled(true)
        .setOAuthConsumerKey("myConsumerKey")
        .setOAuthConsumerSecret("myConsumerSecret")
        .setOAuthAccessToken("myAccessToken")
        .setOAuthAccessTokenSecret("myAccessTokenSecret");

    TwitterFactory tf = new TwitterFactory(cb.build());
    Twitter twitter = tf.getInstance();

    try {
        Query query = new Query("iphone");
        QueryResult result;
        result = twitter.search(query);
        System.out.println("Total amount of tweets: " + result.getTweets().size());
        List<Status> tweets = result.getTweets();

        for (Status tweet : tweets) {
            System.out.println("@" + tweet.getUser().getScreenName() + " : " + tweet.getText());
        }
    } catch (TwitterException te) {
        te.printStackTrace();
        System.out.println("Failed to search tweets: " + te.getMessage());
    }

그리고 여기 오류가 있습니다 :

sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Relevant discussions can be found on the Internet at:
    http://www.google.co.jp/search?q=d35baff5 or
    http://www.google.co.jp/search?q=1446302e
TwitterException{exceptionCode=[d35baff5-1446302e 43208640-747fd158 43208640-747fd158 43208640-747fd158], statusCode=-1, message=null, code=-1, retryAfter=-1, rateLimitStatus=null, version=3.0.5}
    at twitter4j.internal.http.HttpClientImpl.request(HttpClientImpl.java:177)
    at twitter4j.internal.http.HttpClientWrapper.request(HttpClientWrapper.java:61)
    at twitter4j.internal.http.HttpClientWrapper.get(HttpClientWrapper.java:81)
    at twitter4j.TwitterImpl.get(TwitterImpl.java:1929)
    at twitter4j.TwitterImpl.search(TwitterImpl.java:306)
    at jku.cc.servlets.TweetsAnalyzer.main(TweetsAnalyzer.java:38)
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.ssl.Alerts.getSSLException(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.fatal(Unknown Source)
    at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
    at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
    at sun.security.ssl.ClientHandshaker.serverCertificate(Unknown Source)
    at sun.security.ssl.ClientHandshaker.processMessage(Unknown Source)
    at sun.security.ssl.Handshaker.processLoop(Unknown Source)
    at sun.security.ssl.Handshaker.process_record(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
    at java.net.HttpURLConnection.getResponseCode(Unknown Source)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(Unknown Source)
    at twitter4j.internal.http.HttpResponseImpl.<init>(HttpResponseImpl.java:34)
    at twitter4j.internal.http.HttpClientImpl.request(HttpClientImpl.java:141)
    ... 5 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.validator.PKIXValidator.doBuild(Unknown Source)
    at sun.security.validator.PKIXValidator.engineValidate(Unknown Source)
    at sun.security.validator.Validator.validate(Unknown Source)
    at sun.security.ssl.X509TrustManagerImpl.validate(Unknown Source)
    at sun.security.ssl.X509TrustManagerImpl.checkTrusted(Unknown Source)
    at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
    ... 20 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source)
    at java.security.cert.CertPathBuilder.build(Unknown Source)
    ... 26 more
Failed to search tweets: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target



답변

  1. 브라우저에서 URL로 이동하십시오.
    • firefox-HTTPS 인증서 체인 (URL 주소 옆의 잠금 아이콘)을 클릭하십시오. 를 클릭하십시오 "more info" > "security" > "show certificate" > "details" > "export..". 이름을 들고 파일 유형을 선택하십시오.
    • 크롬-주소 표시 줄에 주소를 지정하려면 왼쪽에있는 사이트 아이콘을 클릭하고 “인증서”-> “세부 사항”-> “내보내기”를 선택하고 “Der-encoded binary, single certificate”형식으로 저장하십시오.
  2. 이제 키 저장소가있는 파일이 있으며이를 JVM에 추가해야합니다. cacerts 파일의 위치를 ​​결정하십시오 (예 :
    C:\Program Files (x86)\Java\jre1.6.0_22\lib\security\cacerts.

  3. 다음 example.cer명령 행에서 파일을 cacerts로 가져 오십시오 .

keytool -import -alias example -keystore C:\Program Files (x86)\Java\jre1.6.0_22\lib\security\cacerts -file example.cer

당신은 기본 암호를 묻는 메시지가 나타납니다 changeit

JVM / PC를 다시 시작하십시오.

출처 :
http://magicmonster.com/kb/prg/java/ssl/pkix_path_building_failed.html


답변

Java 6 설치가 새 트위터 인증서와 함께 작동하도록 인증서 파일을 작성하려고 여러 시간을 보낸 후 마침내 메시지 보드 중 하나의 주석에 묻힌 매우 간단한 솔루션을 발견했습니다. Java 7 설치에서 cacerts 파일을 복사하고 Java 6 설치에서 cacerts 파일을 덮어 쓰십시오. cacerts 파일을 먼저 백업하는 것이 가장 좋지만 새 파일을 BOOM에 복사하면됩니다. 그냥 작동합니다.

실제로 Windows cacerts 파일을 Linux 설치에 복사했으며 정상적으로 작동했습니다.

파일은 jre/lib/security/cacerts이전 및 새 Java jdk 설치 모두에 있습니다.

이로 인해 다른 사람이 몇 시간 동안 악화 될 수 있기를 바랍니다.


답변

내 UI 접근 방식 :

  1. 여기 에서 키 스토어 탐색기를 다운로드 하십시오
  2. $ JAVA_HOME / jre / lib / security / cacerts를여십시오.
  3. PW 입력 : changeit (Mac에서는 changeme 가능)
  4. .crt 파일 가져 오기

CMD 라인 :

  1. keytool -importcert -file jetty.crt -alias jetty -keystore $JAVA_HOME/jre/lib/security/cacerts
  2. PW 입력 : changeit(Mac에서는 changeme 가능)

답변

나는 공식 인증서와 달리 자동 생성 된 인증서를 사용하여 수정하는 데 많은 시간이 걸리는이 문제를 우연히 발견했습니다. 공식 인증서와 달리 상당히 까다 롭고 Java는 그렇게 많이 좋아하지 않습니다.

다음 링크를 확인하십시오. Java 인증서 문제 해결

기본적으로 서버에서 Java Home 인증서로 인증서를 추가해야합니다.

  1. 인증서 생성 또는 가져 오기 및 Servers.xml에서 인증서를 사용하도록 Tomcat 구성
  2. 클래스의 Java 소스 코드를 다운로드하여 InstallCert서버가 실행되는 동안 실행하여 다음 인수를 제공하십시오 server[:port]. 원래 비밀번호가 Java 인증서 ( “changeit”)에 대해 작동하므로 비밀번호가 필요하지 않습니다.
  3. 본 프로그램은 서버에 연결되며 Java는 예외를 처리하며, 서버가 제공 한 인증서를 분석 jssecerts하고 프로그램을 실행 한 디렉토리 내에 파일 을 작성할 수 있도록합니다 (Eclipse에서 실행 된 경우 작업을 구성해야합니다) 에 디렉토리 Run -> Configurations).
  4. 해당 파일을 수동으로 복사 $JAVA_HOME/jre/lib/security

이 단계를 수행 한 후에는 인증서와의 연결로 Java 내에서 더 이상 예외가 생성되지 않습니다.

다음 소스 코드는 중요하며 (Sun) Oracle 블로그에서 사라졌으며 제공된 링크에있는 유일한 페이지이므로 참조를 위해 답변에 첨부했습니다.

/*
 * 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.
 */
/**
 * Originally from:
 * http://blogs.sun.com/andreas/resource/InstallCert.java
 * Use:
 * java InstallCert hostname
 * Example:
 *% java InstallCert ecc.fedora.redhat.com
 */

import javax.net.ssl.*;
import java.io.*;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

/**
 * Class used to add the server's certificate to the KeyStore
 * with your trusted certificates.
 */
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 [: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);
        }
    }
}


답변

1. 인증서 확인

브라우저에 대상 URL을로드하고 다른 이유로 만료되었거나 신뢰할 수없는 사이트 인증서 (보통 자물쇠 기호가있는 아이콘으로 액세스 할 수 있습니다. 브라우저 주소 표시 줄의 왼쪽 또는 오른쪽에 있음)를보십시오.

2. 최신 버전의 JRE 및 JDK 설치

새 버전에는 일반적으로 업데이트 된 신뢰할 수있는 인증서 세트가 제공됩니다.

가능하면 이전 버전을 제거하십시오. 잘못된 구성 오류가 명시 적으로 나타납니다.

3. 구성을 확인하십시오.

  • JAVA_HOME 환경 변수가 가리키는 위치를 확인하십시오.
  • 프로그램을 실행하는 데 사용하는 Java 버전을 확인하십시오. IntelliJ 확인에서 :
    • 파일-> 프로젝트 구조 …-> 프로젝트 설정-> 프로젝트-> 프로젝트 SDK :
    • 파일-> 프로젝트 구조 …-> 플랫폼 설정-> SDK

4. 새로운 Java 버전에서 전체 키 저장소를 복사하십시오.

사용 가능한 최신 버전이 아닌 JDK로 개발하는 경우 %JAVA_HOME%/jre/lib/security/cacerts@ jeremy-goodell이 그의 답변 에서 제안한대로 최신 설치된 JRE의 새 파일로 파일 을 바꾸십시오 (먼저 백업 사본 만들기).

5. 키 저장소에 인증서 추가

위의 방법으로 문제를 해결하지 못하면 keytool인증서를 Java의 키 저장소에 저장 하는 데 사용하십시오 .

keytool -trustcacerts -keystore "%JAVA_HOME%jre\lib\security\cacerts" -storepass changeit -importcert -alias <alias_name> -file <path_to_crt_file>

@MagGGG가 그의 답변 에서 제안한대로 인증서를 가진 파일은 브라우저에서 얻을 수 있습니다 .

참고 1 : 사이트 인증서의 체인에있는 모든 인증서에 대해이 작업을 반복해야 할 수도 있습니다. 루트부터 시작하십시오.

참고 2 : <alias_name>상점의 키간에 고유해야하거나 keytool오류가 표시됩니다.

상점에서 모든 인증서 목록을 얻으려면 다음을 실행할 수 있습니다.

keytool -list -trustcacerts -keystore "%JAVA_HOME%jre\lib\security\cacerts" -storepass changeit

문제가 발생하면 저장소에서 인증서를 제거하는 데 도움이됩니다.

keytool -delete -alias <alias_name> -keystore "%JAVA_HOME%jre\lib\security\cacerts" -storepass changeit


답변

-Dmaven.wagon.http.ssl.insecure=true -Dmaven.wagon.http.ssl.allowall=true

인증서 유효성 검사를 점프하는 데 사용됩니다.

경고
이것은 개발 목적으로 만 사용하는 것이 안전하지 않습니다!


답변

JDK와 JRE 1.8.0_112가 모두 시스템에있을 때 상황이 약간 다릅니다.

[JDK_FOLDER]\jre\lib\security\cacerts이미 알려진 명령 을 사용하여 새 CA 인증서를 가져 왔습니다 .

keytool -import -trustcacerts -keystore cacerts -alias <new_ca_alias> -file <path_to_ca_cert_file>

여전히 동일한 PKIX 경로 작성 실패 오류가 계속 발생합니다.

를 사용하여 디버그 정보를 Java CLI에 추가했습니다 java -Djavax.net.debug=all ... > debug.log. debug.log 파일에서 trustStore로 시작하는 행 실제로 다음 에서 찾은 cacerts 저장소를 가리 킵니다 [JRE_FOLDER]\lib\security\cacerts.

필자의 경우 해결책은 JDK에서 사용하는 cacerts 파일 (새로운 CA가 추가 된 파일)을 JRE에서 사용하는 CACerts 파일에 복사하여 문제를 해결하는 것입니다.