“ การสร้างเส้นทาง PKIX ล้มเหลว” และ“ ไม่สามารถค้นหาเส้นทางการรับรองที่ถูกต้องไปยังเป้าหมายที่ร้องขอได้”


422

ฉันพยายามรับ tweets โดยใช้twitter4j library สำหรับโปรเจ็กต์ java ของฉัน ในการทำงานครั้งแรกของฉันฉันมีข้อผิดพลาดเกี่ยวกับใบรับรองและ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

6
สวัสดีกรุณาตรวจสอบ URL ด้านล่าง ฉันมั่นใจว่าสิ่งเหล่านี้จะช่วยคุณได้ java-samples.com/showtutorial.php?tutorialid=210 confluence.atlassian.com/display/JIRAKB/... คุณต้องเพิ่มใบรับรอง ssl ของคุณลงในใบรับรอง java truststore (พา ธ : jre / lib / security / cacerts)
sus007

โปรดดูคำตอบนี้สำหรับวิธีการแก้ปัญหาและยืนยันว่าคุณกำลังบรรจุซอฟต์แวร์ของคุณเป็น jre ที่ให้มาหรือไม่? ถ้าใช่ให้คัดลอกระบบฟอร์มไฟล์ cacerts ของคุณและแทนที่ไฟล์ jre cacerts ที่ทำแพ็กเกจนั้น
positivecrux

ลองนี้stackoverflow.com/a/9210661/4741746นี้อาจจะเป็นคำตอบของคุณ
gosavi Sushant

2
ฉันเพิ่งใช้โค้ดจาวานี้และสำหรับ https อย่าลืมระบุพอร์ตเป็น 443 รหัส Java ที่ github.com/escline/InstallCert/blob/master/InstallCert.java จะใช้ไฟล์ CACERTS ของคุณและจะเพิ่มสิ่งเหล่านั้นบวกทั้งหมด ใบรับรองปัจจุบันของ URL ที่คุณให้เป็นอินพุต ในกรณีของฉันฉัน hardcoded ค่าไปยัง host = "mywebservice.uat.xyz.com"; พอร์ต = 443; ข้อความรหัสผ่าน = "changeit" .toCharArray (); จากนั้นโปรแกรมจะสร้างไฟล์ใหม่ที่ชื่อว่า "jssecacerts" ซึ่งจะมีทุกอย่าง เปลี่ยนชื่อเป็น "cacerts" และใช้สิ่งนี้ คุณจะถูกตั้งค่าทั้งหมด
Reddymails

คำตอบ:


572
  1. ไปที่ URL ในเบราว์เซอร์ของคุณ:
    • firefox - คลิกที่ห่วงโซ่ใบรับรอง HTTPS (ไอคอนล็อคติดกับที่อยู่ URL) "more info" > "security" > "show certificate" > "details" > "export.."คลิก รับชื่อและเลือกประเภทไฟล์ example.cer
    • chrome - คลิกที่ไอคอนไซต์ด้านซ้ายไปยังที่อยู่ในแถบที่อยู่เลือก "ใบรับรอง" -> "รายละเอียด" -> "ส่งออก" และบันทึกในรูปแบบ "Der-encoded binary, ใบรับรองเดี่ยว"
  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


27
ฉันต้องใส่เส้นทางในเครื่องหมายคำพูดและบันทึกเป็น Base64 แทน DER
Theodore K.

3
ว้าว.. มันทำงานเหมือนเวทมนตร์ในโครเมี่ยมคุณเพียงแค่คลิกที่ไอคอนล็อคบนแถบที่อยู่ด้านซ้ายแล้วคลิกรายละเอียด รวมทั้งไม่จำเป็นต้องรีสตาร์ท
aswzen

8
โปรดทราบว่าควรทำซ้ำคำแนะนำสำหรับใบรับรองทั้งหมดในสายโซ่ นอกจากนี้ยังมีใบรับรองของaliasชื่อในบรรทัดคำสั่งต้องไม่ซ้ำกัน
Lu55

5
หากบ้านของคุณเป็น JDK ตรวจสอบให้แน่ใจว่าระบุว่า jre อยู่ในนั้น: keytool -import -alias example -keystore "C: \ Program Files \ Java \ jdk1.8.0_73 \ jre \ lib \ security \ cacerts" -file example.cer
Jack BeNimble

12
สำหรับทุกคนที่ได้รับข้อผิดพลาด "การเข้าถึงถูกปฏิเสธ" ตรวจสอบให้แน่ใจว่าคุณกำลังเรียกใช้พรอมต์คำสั่งในฐานะผู้ดูแลระบบ
Walker Christie

81

หลังจากหลายชั่วโมงที่พยายามสร้างไฟล์ใบรับรองเพื่อให้การติดตั้ง Java 6 ของฉันทำงานกับ twitter cert ใหม่ในที่สุดฉันก็สะดุดกับโซลูชันที่เรียบง่ายอย่างไม่น่าเชื่อฝังอยู่ในความคิดเห็นในกระดานข้อความหนึ่ง เพียงคัดลอกไฟล์ cacerts จากการติดตั้ง Java 7 และเขียนทับไฟล์ในการติดตั้ง Java 6 ของคุณ น่าจะดีที่สุดในการสำรองไฟล์ cacerts ก่อน แต่จากนั้นคุณเพียงแค่คัดลอกไฟล์ใหม่ในและ BOOM! มันใช้งานได้

โปรดทราบว่าฉันคัดลอกไฟล์ cacerts ของ Windows ไปยังการติดตั้ง Linux และมันใช้ได้ดี

ไฟล์อยู่ในjre/lib/security/cacertsทั้งการติดตั้ง Java jdk ทั้งเก่าและใหม่

หวังว่านี่จะช่วยให้ผู้อื่นเดือดดาลชั่วโมง


4
ฉันพยายามเข้าถึงเซิร์ฟเวอร์ ssl ด้วยใบรับรองแบบลงนามด้วยตนเองพยายามเพิ่มใบรับรองโดยใช้ keytool แต่ไม่มีโชคคำแนะนำใด ๆ
Oleg Belousov

1
ดีใจที่มันได้ผล .. แต่คุณรู้หรือไม่ว่าต้นเหตุคืออะไร สิ่งที่ทำให้มันล้มเหลวด้วย java 6 certs .. และ java 7 certs แก้ไขปัญหาได้อย่างไร
Vishwanath gowda k

สิ่งนี้ทำแม้ว่าฉันจะไปจาก icedtea 1.6 ถึง oracle 1.7 :)
nperson325681

พิจารณาโซลูชันนี้ด้วย: stackoverflow.com/questions/33439905/…
Piohen

10
สำหรับคนที่ชอบฉันบางครั้งก็เห็นได้ชัด - ให้แน่ใจว่าคุณกำลังเข้าไป$JAVA_HOME/jre/libไม่ใช่$JAVA_HOME/lib- ฉันใช้เวลาซักนิดในรายละเอียดนั้น
Ryan Heathcote

35

แนวทาง UI ของฉัน:

  1. ดาวน์โหลด keystore explorer จากที่นี่
  2. เปิด $ JAVA_HOME / jre / lib / security / cacerts
  3. ป้อน PW: changeit (สามารถเปลี่ยนได้บน Mac)
  4. นำเข้าไฟล์. crt ของคุณ

CMD-Line:

  1. keytool -importcert -file jetty.crt -alias jetty -keystore $JAVA_HOME/jre/lib/security/cacerts
  2. ป้อน PW: changeit(สามารถเปลี่ยนได้บน Mac)

1
บน mac ด้วย CMD-Line ควรใช้ sudo เพื่อรันคำสั่ง # sudo keytool -importcert -file jetty.crt -alias Jetty -keystore $ JAVA_HOME / jre / lib / ความปลอดภัย / cacerts
malajisi

1
สำหรับ Windows คำสั่งที่ใช้ได้:keytool -importcert -file dinardap_cert.cer –alias dinardap –keystore “%JAVA_HOME%/jre/lib/security/cacerts”
Patricio Bonilla

จะรับไฟล์ใบรับรองได้จากที่ใด ฉันไม่สามารถบอกได้ว่าควรไปที่ URL ใด jetty.com ?
kraftydevil

ฉันได้รับใบรับรองจากการส่งออกจากเว็บเบราว์เซอร์การกระทำตามบริบทบนกุญแจ
rtbf

28

ฉันได้พบกับปัญหานี้ซึ่งใช้เวลาหลายชั่วโมงในการวิจัยเพื่อแก้ไขโดยเฉพาะอย่างยิ่งกับใบรับรองที่สร้างโดยอัตโนมัติซึ่งแตกต่างจากใบรับรองอย่างเป็นทางการค่อนข้างยุ่งยากและ Java ไม่ชอบพวกเขามากนัก

โปรดตรวจสอบลิงค์ต่อไปนี้: แก้ปัญหาเกี่ยวกับใบรับรองใน Java

โดยทั่วไปคุณต้องเพิ่มใบรับรองจากเซิร์ฟเวอร์ไปยัง Java Home certs

  1. สร้างหรือรับใบรับรองของคุณและกำหนดค่า Tomcat เพื่อใช้ใน Servers.xml
  2. ดาวน์โหลดโค้ด Java ของการเรียนและดำเนินการได้ในขณะที่เซิร์ฟเวอร์ทำงานให้ข้อโต้แย้งดังต่อไปนี้InstallCert server[:port]ไม่จำเป็นต้องใช้รหัสผ่านเนื่องจากรหัสผ่านเดิมใช้ได้กับ Java certs ("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);
        }
    }
}

2
หมายเหตุไฟล์ที่สร้างคือ jssecacerts!
DeanDP

ฉันลองใช้วิธีแก้ปัญหานี้สำหรับ Java 7 และ 8 ในขณะที่ทำงานบน Java 7 ฉันได้รับ protocol_version หรือ handshake_failure สำหรับ url ที่เก็บข้อมูลระยะไกลทั้งหมดที่ฉันพยายาม SandeepanNath:test sandeepan.nath$ java InstallCert repo1.maven.org:443 Loading KeyStore /Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home/jre/lib/security/cacerts... Opening connection to repo1.maven.org:443 ... Starting SSL handshake... javax.net.ssl.SSLException: Received fatal alert: protocol_version .. Could not obtain server certificate chain
Sandeepan Nath

20

1. ตรวจสอบใบรับรอง

ลองโหลด URL เป้าหมายในเบราว์เซอร์และดูใบรับรองของเว็บไซต์ (โดยปกติจะสามารถเข้าถึงได้โดยไอคอนพร้อมกับล็อคสัญลักษณ์อยู่ทางด้านซ้ายหรือขวาของแถบที่อยู่ของเบราว์เซอร์) ไม่ว่าจะหมดอายุหรือไม่น่าเชื่อถือด้วยเหตุผลอื่น

2. ติดตั้ง JRE และ JDK เวอร์ชันล่าสุด

เวอร์ชันใหม่มักจะมาพร้อมกับชุดใบรับรองที่เชื่อถือได้ที่อัปเดตแล้ว

นอกจากนี้หากเป็นไปได้ให้ถอนการติดตั้งเวอร์ชันเก่า สิ่งนี้จะทำให้ข้อผิดพลาดการกำหนดค่าผิดพลาดอย่างชัดเจน

3. ตรวจสอบการกำหนดค่าของคุณ:

  • ตรวจสอบว่าตัวแปรสภาพแวดล้อม JAVA_HOME ของคุณชี้ไปที่ใด
  • ตรวจสอบเวอร์ชัน Java ที่คุณใช้เพื่อรันโปรแกรม ใน IntelliJ ตรวจสอบ:
    • ไฟล์ -> โครงสร้างโครงการ ... -> การตั้งค่าโครงการ -> โครงการ -> SDK โครงการ:
    • ไฟล์ -> โครงสร้างโครงการ ... -> การตั้งค่าแพลตฟอร์ม -> SDK

4. คัดลอกที่เก็บคีย์ทั้งหมดจาก Java เวอร์ชันใหม่

หากคุณพัฒนาภายใต้ JDK นอกเหนือจากรุ่นล่าสุดที่มีให้ลองเปลี่ยน%JAVA_HOME%/jre/lib/security/cacertsไฟล์ด้วยไฟล์ใหม่จาก JRE ที่ติดตั้งล่าสุด (ทำสำเนาสำรองก่อน) ตามที่ @ jeremy-goodell แนะนำในไฟล์คำตอบ

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

ด้วยความละเอียดของสิ่งนี้มันควรจะเป็นคำตอบที่ได้รับการยอมรับ
Egor Hans

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

มันถูกใช้สำหรับการข้ามการตรวจสอบใบรับรอง

คำเตือน ใช้เพื่อการพัฒนาเท่านั้นไม่ปลอดภัย!


4
มันใช้สำหรับข้ามการตรวจสอบใบรับรอง
gorums

2
@gorums วิธีการตั้งค่าใน Eclipse
malajisi

6
ห้ามทำสิ่งนี้เว้นแต่ว่าคุณต้องการเสี่ยงที่จะเรียกใช้รหัสที่เป็นอันตรายโดยเจตนาบนเครื่องของคุณ ลดระดับลงเนื่องจากมีความเสี่ยงต่อการสูญเสียเครื่องจักรที่รัน
ไบรอัน

1
เพียงเพราะมันใช้งานได้ไม่ได้หมายความว่าปลอดภัยคุณกำลังทำให้ทุกคนปฏิบัติตามคำแนะนำนี้โดยเสี่ยง มี downvote ของฉัน
Paradoxis

1
@ACEKing ประเด็นก็คือว่ามันไม่ใช่รหัสที่เชื่อถือได้หากคุณไม่ได้ตรวจสอบใบรับรอง ที่กล่าวว่าฉันคิดว่านี่ยังคงเป็นคำตอบที่มีประโยชน์ คนที่ทำมันเพียงแค่ต้องเข้าใจความเสี่ยง
Michael Mior

12

ฉันมีสถานการณ์ที่แตกต่างกันเล็กน้อยเมื่อทั้ง JDK และ JRE 1.8.0_112 ปรากฏในระบบของฉัน

ฉันนำเข้าใบรับรอง CA ใหม่[JDK_FOLDER]\jre\lib\security\cacertsโดยใช้คำสั่งที่รู้จักแล้ว:

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

แต่ถึงกระนั้นฉันยังคงได้รับข้อผิดพลาดในการสร้างเส้นทาง PKIXเดียวกัน

ผมเพิ่มข้อมูลการแก้ปัญหาเพื่อ CLI java -Djavax.net.debug=all ... > debug.logจาวาโดยใช้ ในไฟล์ debug.log บรรทัดที่ขึ้นต้นด้วยtrustStore คือ:จริง ๆ แล้วชี้ไปที่ร้าน cacerts ที่พบ[JRE_FOLDER]\lib\security\cacertsร้านค้าที่พบใน

ในกรณีของฉันวิธีแก้ไขคือการคัดลอกไฟล์ cacerts ที่ใช้โดย JDK (ซึ่งเพิ่ม CA ใหม่) เหนือไฟล์ที่ใช้โดย JRE และแก้ไขปัญหา


ฉันนำเข้า certs ที่ฉันต้องการโดยตรงไปยัง JRE / lib / security / cacerts โดยใช้ keytool แต่มันไม่มีอะไรเปลี่ยนแปลงสำหรับฉัน :( ยังได้รับข้อผิดพลาดเดียวกันฉันยังเพิ่มพวกมันผ่าน IDE หรือแม้แต่ใน classpath และเพิ่ม Bean to ระบุตำแหน่ง keystore !! มันบ้า AF!
Alex

8

พื้นหลังปัญหา:

ฉันได้รับข้อผิดพลาดต่อไปนี้เมื่อฉันพยายามเรียกใช้ mvn clean ติดตั้งในโครงการของฉันและผ่าน Netbeans IDE clean และ build option ปัญหานี้เกิดจากใบรับรองไม่พร้อมใช้งานเมื่อเราดาวน์โหลดผ่าน NET beans IDE / through command command แต่สามารถดาวน์โหลดไฟล์ผ่านเบราว์เซอร์

ข้อผิดพลาด :

Caused by: org.eclipse.aether.transfer.ArtifactTransferException: Could not transfer artifact com.java.project:product:jar:1.0.32 from/to repo-local (https://url/local-repo): sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target  

ความละเอียด:

1. ดาวน์โหลดใบรับรองของ URL ที่เป็นปัญหา:

  • เปิด IE โดย "run as adminstrator" (ไม่เช่นนั้นเราจะไม่สามารถดาวน์โหลดใบรับรอง)
  • ป้อน URL ใน IE-> https: // url / local-repo (ในกรณีของฉัน URL นี้มีใบรับรองที่ไม่น่าเชื่อถือป้อนคำอธิบายรูปภาพที่นี่)
  • ดาวน์โหลดใบรับรองโดยคลิกที่ข้อผิดพลาดใบรับรอง -> ดูใบรับรอง
  • เลือกรายละเอียดแท็บ -> คัดลอกไปยังไฟล์ -> ถัดไป -> เลือก "DER encoded binary X.509 (.CER)
  • บันทึกใบรับรองในบางตำแหน่งตัวอย่าง: c: /user/sheldon/desktop/product.cer
  • ยินดีด้วย! คุณดาวน์โหลดใบรับรองสำหรับไซต์สำเร็จแล้ว

2. ตอนนี้ติดตั้งที่จัดเก็บคีย์เพื่อแก้ไขปัญหา

  • รันคำสั่ง keytool เพื่อผนวกที่เก็บคีย์ที่ดาวน์โหลดลงในไฟล์ใบรับรองที่มีอยู่
  • คำสั่ง: คำสั่งด้านล่างในโฟลเดอร์ bin ของ JDK (JAVA_HOME)

C: \ Program Files \ Java \ jdk1.8.0_141 \ jre \ bin> keytool -importcert -file "C: /user/sheldon/desktop/product.cer" -alias ผลิตภัณฑ์ -keystore "C: / Program Files / Java / jdk1.8.0_141 / JRE / lib / การรักษาความปลอดภัย / cacerts"

  • คุณจะได้รับแจ้งให้ป้อนรหัสผ่าน ป้อนรหัสผ่านที่เก็บคีย์: ป้อน "changeit" อีกครั้งสำหรับ "เชื่อถือใบรับรองนี้หรือไม่ [ไม่]:", ป้อน "ใช่"

ตัวอย่างคำสั่งบรรทัดคำสั่ง / เอาท์พุท:

keytool -importcert -file "C:/Users/sheldon/Desktop/product.cer" -alias product -keystore "C:/Program iles/Java/jdk1.8.0_141/jre/lib/security/cacerts"
Enter keystore password:
Trust this certificate? [no]:  yes
Certificate was added to keystore
  • Contgrats! ตอนนี้คุณควรกำจัด "การสร้างพา ธ PKIX ที่ล้มเหลว: sun.security.provider.certpath.SunCertPathBuilderException" ข้อผิดพลาดใน Netbeans IDE ของคุณ

สวัสดีฉันทำตามทุกขั้นตอน แต่ไม่มีโชค :(
ManishNegi

คุณมีใบรับรองอื่นในเส้นทางอื่นที่ไม่ใช่ cacerts หรือไม่? หากคุณมีคนอื่นลองเพิ่มไปยังใบรับรองนั้น
Barani r

ขอบคุณ @Barani r มันเป็นความผิดพลาดของฉันฉันกำลังรันคำสั่งจาก jre และใช้ JDK ใน eclipse ของฉัน
ManishNegi

ไม่สามารถดาวน์โหลดใบรับรองได้ แต่หลังจาก "ทำงานเป็นผู้ดูแลระบบ" ก็ใช้งานได้ดี
อีก coder

8

ฉันต้องการนำเข้าใบรับรองสำหรับ smtp.gmail.com

วิธีแก้ปัญหาที่ใช้ได้กับฉันเท่านั้นคือ 1. ป้อนคำสั่งเพื่อดูใบรับรองนี้

D: \ openssl \ bin \ openssl.exe s_client -connect smtp.gmail.com:465

  1. คัดลอกและบันทึกบรรทัดระหว่าง "----- BEGIN CERTIFICATE -----" และ "----- END CERTIFICATE -----" ลงในไฟล์ gmail.cer

  2. วิ่ง

    keytool -import -alias smtp.gmail.com -keystore "% JAVA_HOME% / jre / lib / security / cacerts" - ไฟล์ C: \ Users \ Admin \ Desktop \ gmail.cer

  3. ใส่รหัสผ่าน chageit

  4. คลิกใช่เพื่อนำเข้าใบรับรอง

  5. รีสตาร์ท java

ตอนนี้รันคำสั่งและคุณพร้อมที่จะไป


ขอบคุณคน! นั่นช่วยชีวิตฉันไว้ นี่เป็นทางออกที่เหมาะสมในกรณีของฉัน
Andrew Gans

บันทึกวันของฉันด้วย ขอบคุณ.
กริช

6

นี่ไม่ใช่คำตอบเฉพาะของ Twitter แต่นี่เป็นคำถามที่เกิดขึ้นเมื่อคุณค้นหาข้อผิดพลาดนี้ หากระบบของคุณได้รับข้อผิดพลาดนี้เมื่อเชื่อมต่อกับเว็บไซต์ที่ดูเหมือนจะมีใบรับรองที่ถูกต้องเมื่อดูในเว็บเบราว์เซอร์ที่อาจหมายถึงเว็บไซต์ที่มีห่วงโซ่ใบรับรองไม่สมบูรณ์

สำหรับการสรุปปัญหาอย่างย่อ: ผู้ออกใบรับรองจะไม่ใช้ใบรับรองหลักในการลงชื่อเพียงใบรับรองเก่า ๆ แต่พวกเขา (โดยปกติ) ลงชื่อใบรับรองระดับกลางที่มีการตั้งค่าสถานะ Certificate Authority (นั่นคือได้รับอนุญาตให้ลงชื่อใบรับรอง) จากนั้นเมื่อคุณซื้อใบรับรองจาก CA พวกเขาจะลงนาม CSR ของคุณด้วยหนึ่งในใบรับรองกลางเหล่านี้

Java trust store ของคุณน่าจะมี Root Cert ได้ไม่เท่านั้น

ไซต์ที่กำหนดค่าผิดอาจกลับมา เฉพาะใบรับรองที่ลงนามแล้ว ปัญหา: มีการเซ็นชื่อด้วยใบรับรองระดับกลางที่ไม่ได้อยู่ในร้านค้าที่เชื่อถือได้ของคุณ เบราว์เซอร์จะจัดการกับปัญหานี้โดยการดาวน์โหลดหรือใช้ใบรับรองระดับกลางที่แคชไว้ นี่ช่วยเพิ่มความเข้ากันได้ของเว็บไซต์ Java และเครื่องมือเช่น OpenSSL จะไม่ทำเช่นนั้น และนั่นจะทำให้เกิดข้อผิดพลาดในคำถาม

คุณสามารถตรวจสอบความสงสัยนี้ได้โดยใช้การทดสอบ SSL Qualys หากคุณใช้งานกับเว็บไซต์และมันบอกว่า

สายใบรับรองของเซิร์ฟเวอร์นี้ไม่สมบูรณ์

จากนั้นยืนยันมัน คุณยังสามารถดูสิ่งนี้ได้โดยดูที่เส้นทางการรับรองและเห็นข้อความดาวน์โหลดเพิ่มเติมเพิ่มเติม

วิธีแก้ไข: ผู้ดูแลระบบเซิร์ฟเวอร์ต้องกำหนดค่าเว็บเซิร์ฟเวอร์เพื่อส่งคืนใบรับรองระดับกลางเช่นกัน ตัวอย่างเช่น Comodo นี่คือที่ที่.ca-bundleไฟล์มีประโยชน์ ตัวอย่างเช่นในการกำหนดค่า Apache ด้วย mod_ssl คุณจะต้องใช้การSSLCertificateChainFileตั้งค่าการกำหนดค่า สำหรับ nginx คุณต้องต่อใบรับรองกลางและใบรับรองที่ลงนามแล้วและใช้ในการกำหนดค่าใบรับรอง SSL คุณสามารถค้นหาเพิ่มเติมได้โดยค้นหา "กลุ่มใบรับรองที่ไม่สมบูรณ์" ออนไลน์


คุณยอดเยี่ยม ขอบคุณ! ฉันมีปัญหากับ buildout ใหม่ของเซิร์ฟเวอร์ Java ของฉันเพราะฉันลืมลบ # หน้า SSLCertificateChainFile !!! อธิบายได้ดีจริงๆ
KisnardOnline

6

สาเหตุที่เราได้รับข้อผิดพลาดข้างต้นก็คือ JDK นั้นมาพร้อมกับใบรับรอง Certificate Authority (CA) ที่เชื่อถือได้จำนวนมากในไฟล์ที่เรียกว่า 'cacerts' แต่ไฟล์นี้ไม่มีเงื่อนงำของใบรับรองที่เราเซ็นเอง กล่าวอีกนัยหนึ่งไฟล์ cacerts ไม่ได้นำเข้าใบรับรองด้วยตนเองของเราและดังนั้นจึงไม่ถือว่าเป็นนิติบุคคลที่เชื่อถือได้และด้วยเหตุนี้มันทำให้เกิดข้อผิดพลาดดังกล่าวข้างต้น

วิธีแก้ไขข้อผิดพลาดด้านบน

เพื่อแก้ไขข้อผิดพลาดข้างต้นสิ่งที่เราต้องทำก็คือการนำเข้าใบรับรองแบบลงนามด้วยตนเองลงในไฟล์ cacerts

ก่อนอื่นให้ค้นหาไฟล์ cacerts เราจะต้องค้นหาตำแหน่ง JDK หากคุณใช้งานแอพพลิเคชั่นของคุณผ่านหนึ่งในไอดีดเช่น Eclipse หรือ IntelliJ Idea ให้ไปที่การตั้งค่าโปรเจ็กต์และหาตำแหน่งของ JDK ตัวอย่างเช่นในตำแหน่งทั่วไปของไฟล์ cacerts ของ Mac OS จะอยู่ที่ตำแหน่งนี้ / Library / Java / JavaVirtualMachines / {{JDK_version}} / เนื้อหา / Home / jre / lib / ความปลอดภัยบนเครื่องของ Window มันจะอยู่ภายใต้ {{Installation_directory} } / {{JDK_version}} / JRE / lib / การรักษาความปลอดภัย

เมื่อคุณพบไฟล์ cacerts แล้วเราต้องนำเข้าใบรับรองที่ลงชื่อด้วยตนเองของเราไปยังไฟล์ cacerts นี้ ตรวจสอบบทความล่าสุดหากคุณไม่ทราบวิธีการสร้างใบรับรองที่ลงชื่อด้วยตนเองอย่างถูกต้อง

หากคุณไม่มีไฟล์ใบรับรอง (.crt) และเพียงแค่มีไฟล์. jks คุณสามารถสร้างไฟล์. crt ได้โดยใช้คำสั่งด้านล่าง ในกรณีที่คุณมีไฟล์. crt / .pem อยู่แล้วคุณสามารถข้ามคำสั่งด้านล่างได้

## เพื่อสร้างใบรับรองจากที่เก็บคีย์ (ไฟล์. jks) ####

keytool -export -keystore keystore.jks -alias selfsigned -file selfsigned.crt

ขั้นตอนด้านบนจะสร้างไฟล์ชื่อ selfsigned.crt.Now อิมพอร์ตใบรับรองไปที่ cacerts

ตอนนี้เพิ่มใบรับรองลงใน JRE / lib / security / cacerts (trustore)
keytool -importcert -file selfsigned.crt -alias selfsigned -keystore {{cacerts path}}

สำหรับเช่น

keytool -importcert -file selfsigned.nextgen.crt -alias selfsigned.nextgen -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/security/cacerts

เพียงแค่รีสตาร์ทแอปพลิเคชั่นของคุณและมันก็ใช้ได้ดี หากยังใช้งานไม่ได้และได้รับข้อยกเว้น SSL handshake อาจหมายความว่าคุณกำลังใช้โดเมนอื่นจากนั้นลงทะเบียนในใบรับรอง

ลิงก์พร้อมคำอธิบายโดยละเอียดและการแก้ไขทีละขั้นตอนอยู่ที่นี่


4

การเพิ่มcacertsไม่ได้ผลสำหรับฉัน หลังจากเปิดใช้งานเข้าสู่ระบบที่มีธงแล้วมารู้การอ่านจาก-Djavax.net.debug=all Javajssecacerts

นำเข้าสู่การjssecacertsทำงานในที่สุด


2
คำอธิบายที่หายไปที่นี่เป็นที่ Java จะใช้ถ้าปัจจุบันเป็นอย่างอื่นjssecacerts cacerts
มาร์ควิสแห่ง Lorne

3

นี่คือทางออก แต่ในรูปแบบของเรื่องราวของฉันกับปัญหานี้:

ฉันเกือบจะตายลองใช้วิธีแก้ปัญหาทั้งหมดที่ให้ไว้ข้างต้น (เป็นเวลา 3 วัน) และไม่มีอะไรทำงานให้ฉัน

ฉันหมดความหวัง

ฉันติดต่อทีมรักษาความปลอดภัยเกี่ยวกับเรื่องนี้เพราะฉันอยู่หลังพรอกซีและพวกเขาบอกว่าพวกเขาเพิ่งปรับปรุงนโยบายความปลอดภัยของพวกเขาเมื่อเร็ว ๆ นี้

ฉันดุพวกเขาไม่ดีสำหรับการไม่แจ้งผู้พัฒนา

หลังจากนั้นพวกเขาก็ออกไฟล์ "cacerts" ใหม่ซึ่งมีใบรับรองทั้งหมด

ฉันลบไฟล์ cacerts ซึ่งมีอยู่ใน% JAVA_HOME% / jre / lib / security และแก้ไขปัญหาของฉันได้

ดังนั้นหากคุณกำลังประสบปัญหานี้อาจมาจากทีมเครือข่ายของคุณเช่นนี้


2

ฉันเจอคำถามนี้ขณะที่พยายามติดตั้งปลั๊กอิน Cucumber-Eclipse ใน Eclipse ผ่านทางเว็บไซต์อัปเดต ฉันได้รับข้อผิดพลาด SunCertPathBuilderException เดียวกัน:

Unable to read repository at http://cucumber.io/cucumber-eclipse/update-site/content.xml.
    Unable to read repository at http://cucumber.io/cucumber-eclipse/update-site/content.xml.
    sun.security.validator.ValidatorException: PKIX path building failed: 
   sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

ในขณะที่คำตอบอื่น ๆ มีความเหมาะสมและเป็นประโยชน์สำหรับสถานการณ์ของคำถามนี้ แต่พวกเขาก็ไม่ช่วยเหลือและทำให้เข้าใจผิดเกี่ยวกับปัญหาของฉัน

ในกรณีของฉันปัญหาคือ URL ที่ให้ไว้สำหรับไซต์ที่อัปเดตคือ:

https://cucumber.io/cucumber-eclipse/update-site

อย่างไรก็ตามเมื่อนำทางไปยังเบราว์เซอร์มันจะถูกเปลี่ยนเส้นทางไปยัง (สังเกตการเพิ่ม " .github "):

http://cucumber.github.io/cucumber-eclipse/update-site/

ดังนั้นความละเอียดคือเพียงแค่ใช้ URL เว็บไซต์อัปเดตที่เปลี่ยนเส้นทางเมื่อเพิ่มไซต์อัปเดตใน eclipse


3
คุณแน่ใจหรือว่ากำลังตอบคำถามที่ถูกต้อง? ไม่มีการกล่าวถึงแตงกวาในคำถามเดิม ...
Done Data Solutions

ฉันรู้สึกว่าฉันเป็น ผมได้รับข้อผิดพลาด SunCertPathBuilderException เดียวกันและในขณะที่การค้นหาสำหรับการแก้ปัญหาที่พบคำถามนี้เช่นเดียวกับคนนี้ อย่างไรก็ตามพวกเขาทั้งคู่ไม่มีวิธีแก้ปัญหาที่เหมาะสมสำหรับสถานการณ์ของฉัน ฉันไม่ได้พยายามตอบคำถามเฉพาะเกี่ยวกับวิธีเพิ่มไซต์ปลั๊กอิน Cucumber-Eclipse ไปยัง eclipse ฉันต้องการระบุบริบทสำหรับปัญหาที่ฉันเผชิญ (การเปลี่ยนเส้นทาง URL) และอธิบายวิธีการแก้ไข
royfripple

ฉันได้อัปเดตคำตอบเพื่อให้ชัดเจนว่าฉันได้รับข้อผิดพลาดเดียวกันโดยสังเกตว่าปัญหาพื้นฐานและวิธีแก้ไขนั้นแตกต่างกัน ฉันรู้สึกว่าถูกต้องเพราะคนอื่นอาจพบคำถามนี้เมื่อค้นหาข้อผิดพลาดเดียวกัน โปรดพิจารณาเปลี่ยนการลงคะแนนของคุณหากคุณรู้สึกว่าเหมาะสม
royfripple

ขอบคุณ. ทำให้สิ่งต่าง ๆ ชัดเจนขึ้นย้อนกลับ downvote ของฉัน
Done Data Solutions

ยินดีต้อนรับคุณ! และขอขอบคุณที่สละเวลาทบทวนอีกครั้ง
royfripple

2

ฉันกำลังเผชิญกับปัญหาเดียวกันและได้รับการแก้ไขโดยใช้ขั้นตอนง่าย ๆ ด้านล่าง:

1) ดาวน์โหลด InstallCert.java จาก google

2) คอมไพล์โดยใช้javac InstallCert.java

3) เรียกใช้ InstallCert.java โดยใช้ java InstallCert.javaด้วยชื่อโฮสต์และพอร์ต https แล้วกด“ 1” เมื่อขอข้อมูลเข้า มันจะเพิ่ม "localhost" เป็นที่เก็บคีย์ที่เชื่อถือได้และสร้างไฟล์ชื่อ "jssecacerts" ดังนี้:

java InstallCert localhost: 443

4) คัดลอก jssecacerts ลงในโฟลเดอร์ $ JAVA_HOME / jre / lib / security

แหล่งที่มาหลักในการแก้ไขปัญหาที่นี่คือ:

https://ankurjain26.blogspot.in/2017/11/javaxnetsslsslhandshakeexception.html


1

ฉันแก้ไขปัญหานี้ใน Windows Server 2016 ด้วย Java 8 โดยการนำเข้าใบรับรองจากpkcs12ร้านค้าไปยังที่เก็บcacertsคีย์

เส้นทางไปยังร้านค้า pkcs12:
C:\Apps\pkcs12.pfx

เส้นทางสู่ cacerts Java:
C:\Program Files\Java\jre1.8.0_151\lib\security\cacerts

เส้นทางสู่ keytool:
C:\Program Files\Java\jre1.8.0_151\bin

หลังจาก possitioning ไปยังโฟลเดอร์ที่มี keytool ในพร้อมรับคำสั่ง (ในฐานะผู้ดูแล) คำสั่งเพื่อใบรับรองการนำเข้าจากpkcs12จะcacertsเป็นดังนี้:
keytool -v -importkeystore -srckeystore C:\Apps\pkcs12.pfx -srcstoretype PKCS12 -destkeystore "C:\Program Files\Java\jre1.8.0_151\lib\security\cacerts" -deststoretype JKS

คุณจะได้รับแจ้งให้:
1. ใส่รหัสผ่าน keystore ปลายทาง (cacerts pasword ค่าดีฟอลต์คือ "changeit")
2. ป้อนรหัสผ่านที่เก็บคีย์ซอร์ส (รหัสผ่าน pkcs12)


เพื่อให้การเปลี่ยนแปลงมีผลให้รีสตาร์ทเครื่องเซิร์ฟเวอร์ (หรือเพียงแค่รีสตาร์ท JVM)


1
ฉันใช้วิธีนี้กับ Mac และใช้งานได้ ใบรับรองของฉันแน่นอนว่าลงชื่อตัวเองและสร้างขึ้นเพื่อฉันนำเข้าไฟล์. pfx ที่ฉันสร้างขึ้นบนเซิร์ฟเวอร์ windows adfs ของฉัน ใช้ Java 10 สำหรับแอปของฉันขอบคุณ
Shashikant Soni

0

ตามปกติแล้วข้อยกเว้นประเภทนี้จะเกิดขึ้นเมื่อมีความไม่ตรงกันในเส้นทางของใบรับรองที่เชื่อถือได้ ตรวจสอบการกำหนดค่าหรือเส้นทางที่จำเป็นต้องใช้ใบรับรองเซิร์ฟเวอร์นี้เพื่อการสื่อสารที่ปลอดภัย


คุณช่วยบอกการกำหนดค่าที่แน่นอนที่ฉันสามารถติดตั้งใบรับรองได้ไหม จริงฉันมีปัญหาเกี่ยวกับเรื่องนี้ฉันได้ติดตั้งใบรับรองเกี่ยวกับปัญหานี้โดยใช้keytoolซึ่งทำงานได้ประมาณ 20-30 นาทีจากนั้นเซิร์ฟเวอร์ออกข้อผิดพลาดเดียวกันอีกครั้ง โปรดช่วยฉันด้วย ฉันติดค้างในปัญหานี้เป็นเวลา 2 วัน
Deepak Gangore

ฉันคิดว่าใบรับรองมีการเปลี่ยนแปลงทุก ๆ 20-30 นาที
วิษณุนาถโกวดะ k

ฉันประสบปัญหาที่คล้ายกัน แต่ปัญหาคือ: MY java เลือกตำแหน่งเริ่มต้นสำหรับ $ JAVA_HOME / lib / security / cacerts ของแอปพลิเคชัน Java แม้ว่าฉันได้ให้ -Djavax.net.ssl.trustStore = / myapp / app.jks ในเรื่องนี้: stackoverflow.com/questions/33821785/…
Laxman G

0

สำหรับฉันข้อผิดพลาดใบรับรองโผล่ขึ้นมาเพราะฉันมีพู้ทำเล่นทำงานในพื้นหลังและที่ยุ่งกับใบรับรอง มันทำหน้าที่เป็นพร็อกซีให้ปิดและเริ่มต้น eclipse ใหม่


ปัญหาเดียวกันที่เกิดขึ้นใน eclipse แม้หลังจากปิดแอปพลิเคชันทั้งหมด
arvindwill

0

เป้าหมาย:

  1. ใช้การเชื่อมต่อ https
  2. ตรวจสอบเครือข่าย SSL
  3. อย่าจัดการกับ cacerts
  4. เพิ่มใบรับรองในรันไทม์
  5. อย่าทำใบรับรองหายจาก cacerts

ทำอย่างไร:

  1. กำหนดที่เก็บคีย์ของตัวเอง
  2. ใส่ใบรับรองลงในที่เก็บคีย์
  3. กำหนดบริบทเริ่มต้น SSL ใหม่ด้วยคลาสที่กำหนดเองของเรา
  4. ???
  5. กำไร

ไฟล์ wrapper ของฉัน Keystore:

public class CertificateManager {

    private final static Logger logger = Logger.getLogger(CertificateManager.class);

    private String keyStoreLocation;
    private String keyStorePassword;
    private X509TrustManager myTrustManager;
    private static KeyStore myTrustStore;

    public CertificateManager(String keyStoreLocation, String keyStorePassword) throws Exception {
        this.keyStoreLocation = keyStoreLocation;
        this.keyStorePassword = keyStorePassword;
        myTrustStore = createKeyStore(keyStoreLocation, keyStorePassword);
    }

    public void addCustomCertificate(String certFileName, String certificateAlias)
            throws Exception {
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init((KeyStore) null);
        Certificate certificate = myTrustStore.getCertificate(certificateAlias);
        if (certificate == null) {
            logger.info("Certificate not exists");
            addCertificate(certFileName, certificateAlias);
        } else {
            logger.info("Certificate exists");
        }
        tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(myTrustStore);
        for (TrustManager tm : tmf.getTrustManagers()) {
            if (tm instanceof X509TrustManager) {
                setMytrustManager((X509TrustManager) tm);
                logger.info("Trust manager found");
                break;
            }
        }
    }

    private InputStream fullStream(String fname) throws IOException {
        ClassLoader classLoader = getClass().getClassLoader();
        InputStream resource = classLoader.getResourceAsStream(fname);
        try {
            if (resource != null) {
                DataInputStream dis = new DataInputStream(resource);
                byte[] bytes = new byte[dis.available()];
                dis.readFully(bytes);
                return new ByteArrayInputStream(bytes);
            } else {
                logger.info("resource not found");
            }
        } catch (Exception e) {
            logger.error("exception in certificate fetching as resource", e);
        }
        return null;
    }

    public static KeyStore createKeyStore(String keystore, String pass) throws Exception {
        try {
            InputStream in = CertificateManager.class.getClass().getResourceAsStream(keystore);
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(in, pass.toCharArray());
            logger.info("Keystore was created from resource file");
            return keyStore;
        } catch (Exception e) {
            logger.info("Fail to create keystore from resource file");
        }

        File file = new File(keystore);
        KeyStore keyStore = KeyStore.getInstance("JKS");
        if (file.exists()) {
            keyStore.load(new FileInputStream(file), pass.toCharArray());
            logger.info("Default keystore loaded");
        } else {
            keyStore.load(null, null);
            keyStore.store(new FileOutputStream(file), pass.toCharArray());
            logger.info("New keystore created");
        }
        return keyStore;
    }

    private void addCertificate(String certFileName, String certificateAlias) throws CertificateException,
            IOException, KeyStoreException, NoSuchAlgorithmException {
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        InputStream certStream = fullStream(certFileName);
        Certificate certs = cf.generateCertificate(certStream);
        myTrustStore.setCertificateEntry(certificateAlias, certs);
        FileOutputStream out = new FileOutputStream(getKeyStoreLocation());
        myTrustStore.store(out, getKeyStorePassword().toCharArray());
        out.close();
        logger.info("Certificate pushed");
    }

    public String getKeyStoreLocation() {
        return keyStoreLocation;
    }

    public String getKeyStorePassword() {
        return keyStorePassword;
    }
    public X509TrustManager getMytrustManager() {
        return myTrustManager;
    }
    public void setMytrustManager(X509TrustManager myTrustManager) {
        this.myTrustManager = myTrustManager;
    }
}

คลาสนี้จะสร้างที่เก็บคีย์หากจำเป็นและจะสามารถจัดการใบรับรองที่อยู่ภายในได้ ตอนนี้คลาสสำหรับบริบท SSL:

public class CustomTrustManager implements X509TrustManager {

    private final static Logger logger = Logger.getLogger(CertificateManager.class);

    private static SSLSocketFactory socketFactory;
    private static CustomTrustManager instance = new CustomTrustManager();
    private static List<CertificateManager> register = new ArrayList<>();

    public static CustomTrustManager getInstance() {
        return instance;
    }

    private X509TrustManager defaultTm;

    public void register(CertificateManager certificateManager) {
        for(CertificateManager manager : register) {
            if(manager == certificateManager) {
                logger.info("Certificate manager already registered");
                return;
            }
        }
        register.add(certificateManager);
        logger.info("New Certificate manager registered");
    }

    private CustomTrustManager() {
        try {
            String algorithm = TrustManagerFactory.getDefaultAlgorithm();
            TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);

            tmf.init((KeyStore) null);
            boolean found = false;
            for (TrustManager tm : tmf.getTrustManagers()) {
                if (tm instanceof X509TrustManager) {
                    defaultTm = (X509TrustManager) tm;
                    found = true;
                    break;
                }
            }
            if(found) {
                logger.info("Default trust manager found");
            } else {
                logger.warn("Default trust manager was not found");
            }

            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, new TrustManager[]{this}, null);
            SSLContext.setDefault(sslContext);
            socketFactory = sslContext.getSocketFactory();
            HttpsURLConnection.setDefaultSSLSocketFactory(socketFactory);


            logger.info("Custom trust manager was set");
        } catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) {
            logger.warn("Custom trust manager can't be set");
            e.printStackTrace();
        }
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        List<X509Certificate> out = new ArrayList<>();
        if (defaultTm != null) {
            out.addAll(Arrays.asList(defaultTm.getAcceptedIssuers()));
        }
        int defaultCount = out.size();
        logger.info("Default trust manager contain " + defaultCount + " certficates");
        for(CertificateManager manager : register) {
            X509TrustManager customTrustManager = manager.getMytrustManager();
            X509Certificate[] issuers = customTrustManager.getAcceptedIssuers();
            out.addAll(Arrays.asList(issuers));
        }
        logger.info("Custom trust managers contain " + (out.size() - defaultCount) + " certficates");
        X509Certificate[] arrayOut = new X509Certificate[out.size()];
        return out.toArray(arrayOut);
    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain,
                                   String authType) throws CertificateException {
        for(CertificateManager certificateManager : register) {
            X509TrustManager customTrustManager = certificateManager.getMytrustManager();
            try {
                customTrustManager.checkServerTrusted(chain, authType);
                logger.info("Certificate chain (server) was aproved by custom trust manager");
                return;
            } catch (Exception e) {
            }
        }
        if (defaultTm != null) {
            defaultTm.checkServerTrusted(chain, authType);
            logger.info("Certificate chain (server) was aproved by default trust manager");
        } else {
            logger.info("Certificate chain (server) was rejected");
            throw new CertificateException("Can't check server trusted certificate.");
        }
    }

    @Override
    public void checkClientTrusted(X509Certificate[] chain,
                                   String authType) throws CertificateException {
        try {
            if (defaultTm != null) {
                defaultTm.checkClientTrusted(chain, authType);
                logger.info("Certificate chain (client) was aproved by default trust manager");
            } else {
                throw new NullPointerException();
            }
        } catch (Exception e) {
            for(CertificateManager certificateManager : register) {
                X509TrustManager customTrustManager = certificateManager.getMytrustManager();
                try {
                    customTrustManager.checkClientTrusted(chain, authType);
                    logger.info("Certificate chain (client) was aproved by custom trust manager");
                    return;
                } catch (Exception e1) {
                }
            }
            logger.info("Certificate chain (client) was rejected");
            throw new CertificateException("Can't check client trusted certificate.");
        }
    }

    public SSLSocketFactory getSocketFactory() {
        return socketFactory;
    }
}

คลาสนี้สร้างเป็น singleton เนื่องจากอนุญาตบริบทบริบท SSL เดียวเท่านั้น ดังนั้นตอนนี้การใช้งาน:

            CertificateManager certificateManager = new CertificateManager("C:\\myapplication\\mykeystore.jks", "changeit");
            String certificatePath = "C:\\myapplication\\public_key_for_your_ssl_service.crt";
            try {
                certificateManager.addCustomCertificate(certificatePath, "alias_for_public_key_for_your_ssl_service");
            } catch (Exception e) {
                log.error("Can't add custom certificate");
                e.printStackTrace();
            }
            CustomTrustManager.getInstance().register(certificateManager);

อาจเป็นไปได้ว่ามันจะไม่ทำงานกับการตั้งค่านี้เพราะฉันเก็บไฟล์ใบรับรองไว้ในโฟลเดอร์ทรัพยากรดังนั้นเส้นทางของฉันจึงไม่สมบูรณ์ แต่โดยทั่วไปแล้วมันทำงานได้อย่างสมบูรณ์แบบ


1
การใช้งานในทางที่ผิดสองครั้งนี้available()ถูกเตือนเป็นการเฉพาะใน Javadoc ของตัวเอง
มาร์ควิสแห่ง Lorne

0

มันนอกจากคำตอบhttps://stackoverflow.com/a/36427118/1491414 ขอบคุณ @MagGGG

  • โปรดตรวจสอบให้แน่ใจว่าคุณได้รับอนุญาตจากผู้ดูแลระบบ
  • กรุณาใช้เครื่องหมายคำพูดคู่สำหรับเส้นทางที่เก็บคีย์ (-keystore C: \ Program Files (x86) \ Java \ jre1.6.0_22 \ lib \ security \ cacerts ") เพราะใน Windows OS ตำแหน่งการติดตั้งเริ่มต้นจะเป็น Program Files และคุณจะได้รับ ข้อผิดพลาดเนื่องจากช่องว่างระหว่าง Program Files

0

ฉันแก้ไขสิ่งนี้โดยใช้วิธีการด้านล่าง -

  1. คัดลอก URL ที่มีปัญหาการเชื่อมต่อ
  2. ไปที่ Android Studio-> Settings-> Http settings
  3. ใน 'ทดสอบการเชื่อมต่อ' ให้วาง URL นั้นแล้วกดตกลง
  4. เมื่อคลิกตกลงแล้ว Android Studio จะขอให้นำเข้าใบรับรองของ URL นั้นนำเข้า
  5. แค่นั้นแหละ. ไม่มีอะไรให้ทำและปัญหาของฉันก็หายไป ไม่จำเป็นต้องรีสตาร์ทสตูดิโอเช่นกัน

0

เมื่อคุณมีข้อผิดพลาดข้างต้นกับซอฟต์แวร์ atlassian เช่น Jira

2018-08-18 11:35:00,312 Caesium-1-4 WARN anonymous    Default Mail Handler [c.a.mail.incoming.mailfetcherservice] Default Mail Handler[10001]: javax.mail.MessagingException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target while connecting to host 'imap.xyz.pl' as user 'jira@xyz.pl' via protocol 'imaps, 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

คุณสามารถเพิ่ม certs ให้กับ keystore ที่เชื่อถือได้ (เปลี่ยน missing_ca เป็นชื่อใบรับรองที่เหมาะสม):

keytool -importcert -file missing_ca.crt -alias missing_ca -keystore /opt/atlassian/jira/jre/lib/security/cacerts

ถ้าถามรหัสผ่านใส่changeitและยืนยันy

หลังจากนั้นให้รีสตาร์ท jira


0

หาก URL ที่เก็บของคุณยังทำงานกับ HTTP และความปลอดภัยไม่ได้เกี่ยวข้องคุณสามารถไปที่settings.xml (บ่อยครั้ง แต่ไม่เสมอไปอยู่ใน%USERPROFILE%/.m2) และแทนที่ HTTPS ด้วย HTTPสำหรับ<repository>และ<pluginRepository>URL

ตัวอย่างเช่นสิ่งนี้:

<repository>
    <snapshots>
        <enabled>false</enabled>
    </snapshots>
    <id>central</id>
    <name>libs-release</name>
    <url>https://<artifactory>/libs-release</url>
</repository>

ควรถูกแทนที่ด้วยสิ่งนี้:

<repository>
    <snapshots>
        <enabled>false</enabled>
    </snapshots>
    <id>central</id>
    <name>libs-release</name>
    <url>https://<artifactory>/libs-release</url>
</repository>

0

ฉันใช้ Trust store ของตัวเองแทนที่จะผ่าน JRE โดยผ่าน ARG -Djavax.net.ssl.trustStore=

ฉันได้รับข้อผิดพลาดนี้โดยไม่คำนึงถึง certs ใน truststore ปัญหาสำหรับฉันคือการเรียงลำดับของคุณสมบัติที่ส่งผ่านบนบรรทัด ARG เมื่อฉันใส่-Djavax.net.ssl.trustStore=& -Djavax.net.ssl.trustStorePassword= ก่อน -Dspring.config.location= & -jarargs ฉันสามารถเรียกส่วนที่เหลือของฉันผ่าน https


0

หากคุณกำลังใช้ CloudFoundry และพบปัญหาใบรับรองคุณต้องตรวจสอบให้แน่ใจว่าคุณได้กด jar อีกครั้งด้วยบริการที่เก็บคีย์พร้อมใบรับรองในนั้น เพียงแค่ผูกผูกและรีสตาร์ทจะไม่ทำงาน


0

ในกรณีที่โฮสต์ของคุณตั้งอยู่หลังไฟร์วอลล์ / พรอกซีใช้คำสั่งต่อไปนี้ใน cmd:

keytool -J-Dhttps.proxyHost=<proxy_hostname> -J-Dhttps.proxyPort=<proxy_port> -printcert -rfc -sslserver <remote_host_name:remote_ssl_port>

แทนที่<proxy_hostname>และ<proxy_port>ด้วยพร็อกซีเซิร์ฟเวอร์ HTTP ที่กำหนดค่า แทนที่<remote_host_name:remote_ssl_port>ด้วยหนึ่งในโฮสต์ระยะไกล (โดยทั่วไป url) และพอร์ตที่มีปัญหาการรับรอง

ใช้เนื้อหาใบรับรองล่าสุดที่พิมพ์และคัดลอก (เช่นคัดลอกใบรับรองเริ่มต้นและสิ้นสุด) วางในไฟล์ข้อความและให้ ส่วนขยาย. crt ตอนนี้อิมพอร์ตใบรับรองนี้ไปยังcacertsโดยใช้คำสั่ง java keytool และควรใช้ได้

keytool -importcert -file <filename>.crt -alias randomaliasname -keystore %JAVA_HOME%/jre/lib/security/cacerts -storepass changeit


0

หากคุณเห็นปัญหานี้ในคอนเทนเนอร์ linux เมื่อแอ็พพลิเคชัน java พยายามสื่อสารกับแอ็พพลิเคชัน / ไซต์อื่นนั่นเป็นเพราะใบรับรองได้รับการนำเข้าอย่างไม่ถูกต้องไปยัง load balancer มีลำดับขั้นตอนที่ต้องปฏิบัติตามสำหรับการนำเข้าใบรับรองและหากทำไม่ถูกต้องคุณจะพบปัญหาเช่น

Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid 
certification path to requested target

เมื่อนำเข้า certs ถูกต้องแล้วก็ควรทำ ไม่จำเป็นต้องคนจรจัดกับ JDK certs ใด ๆ


0

ฉันแก้ปัญหาสำหรับIntellij ฉันพบปัญหานี้แล้วฉันเปลี่ยนสถานที่มากมายเพื่อแก้ไขปัญหาฉันพบวิธีแก้ปัญหาสำหรับฉันคลิกขวาที่โครงการของคุณคุณจะเห็นMavenหลังจากนั้นกดสร้างแหล่งที่มาและอัปเดตโฟลเดอร์และนำเข้าใหม่ ป้อนคำอธิบายรูปภาพที่นี่

มันทำ


0

ฉันกำลังเผชิญปัญหาเดียวกันฉันใช้ 8.1.0-3 แต่ต่อมาฉันใช้ 9.2.1-0 และปัญหาได้รับการแก้ไขโดยไม่มีขั้นตอนใด ๆ ใบรับรองที่ลงนามเองทำงานได้ดี

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.