การแก้ไข javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: การสร้างเส้นทาง PKIX ล้มเหลว?


426

แก้ไข: -พยายามจัดรูปแบบคำถามและคำตอบที่ยอมรับได้ในแบบที่เป็นไปได้มากขึ้นที่บล็อกของฉัน

นี่คือปัญหาดั้งเดิม

ฉันได้รับข้อผิดพลาดนี้:

ข้อความรายละเอียด sun.security.validator.ValidatorException: การสร้างเส้นทาง PKIX ล้มเหลว:
sun.security.provider.certpath.SunCertPathBuilderException: ไม่สามารถค้นหาเส้นทางการรับรองที่ถูกต้องไปยังเป้าหมายที่ร้องขอ

สาเหตุ javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: การสร้างเส้นทาง PKIX ล้มเหลว: sun.security.provider.certpath.SunCertPathBuilderException: ไม่สามารถค้นหาเส้นทางการรับรองที่ถูกต้องไปยังเป้าหมายที่ร้องขอ

ฉันใช้ Tomcat 6 เป็นเว็บเซิร์ฟเวอร์ ฉันมี HTTPS เว็บแอปพลิเคชั่นสองตัวติดตั้งบน Tomcats ที่แตกต่างกันบนพอร์ตที่ต่างกัน แต่ในเครื่องเดียวกัน พูดและApp1(port 8443) เชื่อมต่อกับ เมื่อเชื่อมต่อกับฉันได้รับข้อผิดพลาดดังกล่าว ฉันรู้ว่านี่เป็นข้อผิดพลาดที่พบบ่อยมากดังนั้นจึงพบกับโซลูชันมากมายในฟอรัมและไซต์ต่างๆ ฉันมีรายการด้านล่างในTomcats ทั้งสอง:App2(port 443)App1App2App1App2server.xml

keystoreFile="c:/.keystore" 
keystorePass="changeit"

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

ตัวเลือกที่ 1

System.setProperty("javax.net.ssl.trustStore", "C:/.keystore");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");

ตัวเลือก 2 การตั้งค่าด้านล่างในตัวแปรสภาพแวดล้อม

CATALINA_OPTS -- param name
-Djavax.net.ssl.trustStore=C:\.keystore -Djavax.net.ssl.trustStorePassword=changeit ---param value

ตัวเลือก 3 การตั้งค่าด้านล่างในตัวแปรสภาพแวดล้อม

JAVA_OPTS -- param name
-Djavax.net.ssl.trustStore=C:\.keystore -Djavax.net.ssl.trustStorePassword=changeit ---param value

แต่ไม่มีอะไรทำงาน

สิ่งที่ทำงานล่าสุด คือการเรียกใช้วิธีการ Java ที่แนะนำในวิธีการจัดการใบรับรอง SSL ที่ไม่ถูกต้องกับ Apache HttpClient โดย Pascal Thivent คือการใช้งานโปรแกรม InstallCert

แต่วิธีนี้ใช้ได้สำหรับการตั้งค่า devbox แต่ฉันไม่สามารถใช้งานได้ในสภาพแวดล้อมการผลิต

ฉันกำลังสงสัยว่าทำไมสามวิธีดังกล่าวข้างต้นไม่ได้ทำงานเมื่อผมได้กล่าวถึงค่าเดียวกันในserver.xmlของapp2เซิร์ฟเวอร์เดียวกันค่าใน truststore โดยการตั้งค่า

System.setProperty("javax.net.ssl.trustStore", "C:/.keystore") and System.setProperty("javax.net.ssl.trustStorePassword", "changeit");

ใน app1โปรแกรม

สำหรับข้อมูลเพิ่มเติมนี่คือวิธีที่ฉันทำการเชื่อมต่อ:

URL url = new URL(urlStr);

URLConnection conn = url.openConnection();

if (conn instanceof HttpsURLConnection) {

  HttpsURLConnection conn1 = (HttpsURLConnection) url.openConnection();

  conn1.setHostnameVerifier(new HostnameVerifier() {
    public boolean verify(String hostname, SSLSession session) {
      return true;
    }
  });

  reply.load(conn1.getInputStream());

อาจเป็นไปได้ซ้ำกับHttpClient และ SSL
Marquis ของ Lorne

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

อีกสิ่งหนึ่งที่ควรตรวจสอบคือคุณมี Java เวอร์ชันล่าสุด - ฉันได้รับข้อผิดพลาดคล้ายกันเนื่องจากสิ่งนี้
Redzarf

stackoverflow.com/questions/2893819/… - มีความเกี่ยวข้องและเป็นคำตอบที่ยอดเยี่ยม
Siddhartha

คำตอบ:


406

คุณต้องเพิ่มใบรับรองสำหรับApp2ไปยังแฟ้ม truststore ของ JVM %JAVA_HOME%\lib\security\cacertsสินค้าตั้งอยู่ที่

ก่อนอื่นคุณสามารถตรวจสอบว่าใบรับรองของคุณอยู่ใน truststore หรือไม่โดยเรียกใช้คำสั่งต่อไปนี้: keytool -list -keystore "%JAVA_HOME%/jre/lib/security/cacerts"(คุณไม่จำเป็นต้องใส่รหัสผ่าน)

หากใบรับรองของคุณหายไปคุณสามารถขอรับได้โดยดาวน์โหลดด้วยเบราว์เซอร์ของคุณและเพิ่มลงใน truststore ด้วยคำสั่งต่อไปนี้:

keytool -import -noprompt -trustcacerts -alias <AliasName> -file <certificate> -keystore <KeystoreFile> -storepass <Password>

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

ข้อมูลดวงอาทิตย์ / ออราเคิลสามารถพบได้ที่นี่


6
คุณจะต้องใช้เส้นทางแบบเต็มเช่น c: \ java \ jdk \ lib \ security \ cacerts
SimonSez

48
เช่นเดียวกับ SimonSez กล่าวว่าคุณไม่จำเป็นต้องใช้รหัสผ่าน แต่ถ้าคุณต้องการรหัสผ่านเริ่มต้นคือ "changeit"
เฟลิกซ์

16
นอกจากนี้ใน Windows คุณต้องเรียกใช้ Terminal ในฐานะผู้ดูแลระบบมิฉะนั้นคุณจะได้รับข้อผิดพลาดkeytool error: java.io.FileNotFoundException ... (Access is denied)เมื่อคุณพยายามนำเข้าใบรับรองของคุณ
เฟลิกซ์

2
Ah @SimonSez คุณคือพระเจ้าของฉัน แต่ในการเพิ่มเข้าไปนั้นต้องระบุที่ตั้งที่เชื่อถือได้และรหัสผ่านตามที่ระบุไว้โดย @M Sach เพื่อให้สามารถใช้งานได้
BudsNanKis

2
ยังคงมีปัญหากับ Java 1.8 จำเป็นต้องเพิ่มใบรับรองตามที่อธิบายไว้และใช้ Java <1.8
Tom Howard

180

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: การสร้างเส้นทาง PKIX ล้มเหลว: sun.security.provider.certpath.SunCertPathBuilderException: ไม่สามารถค้นหาเส้นทางการรับรองที่ถูกต้องไปยังเป้าหมายที่ร้องขอ

•เมื่อฉันได้รับข้อผิดพลาดฉันพยายามทำให้ Google เข้าใจความหมายของนิพจน์และพบว่าปัญหานี้เกิดขึ้นเมื่อเซิร์ฟเวอร์เปลี่ยนใบรับรอง HTTPS SSL ของพวกเขาและ Java รุ่นเก่าของเราไม่รู้จักผู้มีสิทธิ์ออกใบรับรองรูท (CA) .

•หากคุณสามารถเข้าถึง HTTPS URL ในเบราว์เซอร์ของคุณเป็นไปได้ที่จะอัปเดต Java เพื่อให้รู้จักรูท CA

•ในเบราว์เซอร์ของคุณไปที่ HTTPS URL ที่ Java ไม่สามารถเข้าถึงได้ คลิกที่ห่วงโซ่ใบรับรอง HTTPS (มีไอคอนล็อคใน Internet Explorer) คลิกที่ล็อคเพื่อดูใบรับรอง

•ไปที่“ รายละเอียด” ของใบรับรองและ“ คัดลอกไปยังไฟล์” คัดลอกในรูปแบบBase64 (.cer) มันจะถูกบันทึกไว้บนเดสก์ท็อปของคุณ

•ติดตั้งใบรับรองโดยไม่สนใจการแจ้งเตือนทั้งหมด

•นี่คือวิธีที่ฉันรวบรวมข้อมูลใบรับรองของ URL ที่ฉันพยายามเข้าถึง

ตอนนี้ฉันต้องทำให้รุ่น java ของฉันรู้เกี่ยวกับใบรับรองเพื่อที่จะได้ไม่ต้องจดจำ URL ในส่วนนี้ฉันต้องพูดถึงว่าฉันออกจากข้อมูลใบรับรองรูทโดยค่าเริ่มต้นในตำแหน่ง\ jre \ lib \ securityของ JDK และรหัสผ่านเริ่มต้นในการเข้าถึงคือ: changeit

ในการดูข้อมูล cacerts ต่อไปนี้เป็นขั้นตอนที่ต้องปฏิบัติตาม:

•คลิกที่ปุ่ม Start -> Run

•พิมพ์ cmd พรอมต์คำสั่งจะเปิดขึ้น (คุณอาจต้องเปิดเป็นผู้ดูแลระบบ)

•ไปที่Java/jreX/binไดเรกทอรีของคุณ

•พิมพ์ดังต่อไปนี้

รายการ keytool -keystore D: \ Java \ jdk1.5.0_12 \ jre \ lib \ security \ cacerts

มันแสดงรายการของใบรับรองปัจจุบันที่มีอยู่ภายในที่เก็บคีย์ ดูเหมือนว่า:

C: \ Documents and Settings \ NeelanjanaG> keytool -list -keystore D: \ Java \ jdk1.5.0_12 \ jre \ lib \ security \ cacerts

ป้อนรหัสผ่านที่เก็บคีย์: changeit

ประเภทที่เก็บคีย์: jks

ผู้ให้บริการที่เก็บคีย์: SUN

ที่เก็บคีย์ของคุณมี 44 รายการ

verisignclass3g2ca, 26 มี.ค. 2004, ที่เชื่อถือได้ใบรับรองพยายาม,

ใบรับรองลายนิ้วมือ (MD5): A2: 33: 9B: 4C: 74: 78: 73: D4: 6C: E7: C1: F3: 8D: CB: 5C: E9

entrustclientca, 9 ม.ค. 2546, TrustedCertEntry,

ใบรับรองลายนิ้วมือ (MD5): 0C: 41: 2F: 13: 5B: A0: 54: F5: 96: 66: 2D: 7E: CD: 0E: 03: F4

thawtepersonalbasicca, 13 ก.พ. 2542, คนที่เชื่อถือได้ใบรับรองพยายาม,

ใบรับรองลายนิ้วมือ (MD5): E6: 0B: D2: C9: CA: 2D: 88: DB: 1A: 71: 0E: 4B: 78: EB: 02: 41

addtrustclass1ca, วันที่ 1 พฤษภาคม 2549, TrustedCertEntry,

ใบรับรองลายนิ้วมือ (MD5): 1E: 42: 95: 02: 33: 92: 6B: B9: 5F: C0: 7F: DA: D6: B2: 4B: FC

verisignclass2g3ca, 26 มี.ค. 2004, ที่เชื่อถือได้ใบรับรองพยายาม,

ใบรับรองลายนิ้วมือ (MD5): F8: BE: C4: 63: 22: C9: A8: 46: 74: 8B: B8: 1D: 1E: 4A: 2B: F6

•ตอนนี้ฉันต้องรวมใบรับรองที่ติดตั้งไว้ก่อนหน้านี้ลงใน cacerts

•สำหรับขั้นตอนต่อไปนี้เป็นขั้นตอน:

keytool –import –noprompt –trustcacerts –alias ALIASNAME -file FILENAME_OF_THE_INSTALLED_CERTIFICATE -keystore PATH_TO_CACERTS_FILE - ที่เก็บรหัสผ่าน

หากคุณใช้ Java 7:

keytool –importcert –trustcacerts –alias ALIASNAME - ไฟล์ PATH_TO_FILENAME_OF_THE_INSTALLED_CERTIFICATE -keystore PATH_TO_CACERTS_FILE - การเปลี่ยนผ่านที่เก็บ

•จากนั้นจะเพิ่มข้อมูลใบรับรองลงในไฟล์ cacert

มันเป็นวิธีการแก้ปัญหาที่ฉันพบสำหรับข้อยกเว้นดังกล่าวข้างต้น !!


5
คุณจะทำอย่างไรเมื่อใบรับรองหมดอายุ ทำซ้ำทุกอย่าง (ทุกปี)?
ggkmath

7
มีวิธีการทำโปรแกรมนี้หรือไม่?
Meshulam Silk

1
สำหรับผู้ที่จัดการกับข้อผิดพลาดของ PKIX "เส้นทางไม่เชื่อมโยงกับจุดยึดที่เชื่อถือได้" วิธีนี้ไม่ได้แก้ปัญหานั้นสำหรับฉันอย่างน่าเสียดาย
IcedDante

3
คำถามเดียว - aliasName เป็นที่อยู่เว็บที่เรานำเข้าใบรับรองหรือไม่ ตัวอย่างเช่นหาก URL คือdomain.site.com/pages/service.asmxควรเป็นชื่อโดเมน domain.com หรือ URL ที่สมบูรณ์ (domain.site.com/pages/service.asmx) หรือควรนำหน้าด้วย http : // หรือมันเป็นเพียงชื่อโดยพลการ
nanosoft

1
เส้นทาง: \ lib \ security> keytool -import -noprompt -trustcacerts -alias webCert -file webCertResource.cer -keystore c: / ผู้ใช้ / Jackie / Desktop - การเปลี่ยนผ่านทางอ้อมฉันได้รับ "ระบบไม่พบไฟล์ที่ระบุ"
Jesse

46

วิธีการทำงานใน Tomcat 7

ฉันต้องการสนับสนุนใบรับรองที่ลงชื่อด้วยตนเองในแอป Tomcat แต่ตัวอย่างต่อไปนี้ไม่สามารถใช้งานได้

import java.io.DataOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class HTTPSPlayground {
    public static void main(String[] args) throws Exception {

        URL url = new URL("https:// ... .com");
        HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();

        httpURLConnection.setRequestMethod("POST");
        httpURLConnection.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
        httpURLConnection.setDoOutput(true);
        DataOutputStream wr = new DataOutputStream(httpURLConnection.getOutputStream());

        String serializedMessage = "{}";
        wr.writeBytes(serializedMessage);
        wr.flush();
        wr.close();

        int responseCode = httpURLConnection.getResponseCode();
        System.out.println(responseCode);
    }
}

นี่คือสิ่งที่แก้ไขปัญหาของฉัน:

1) ดาวน์โหลด.crtไฟล์

echo -n | openssl s_client -connect <your domain>:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ~/<your domain>.crt
  • แทนที่<your domain>ด้วยโดเมนของคุณ (เช่นjossef.com)

2) ใช้.crtไฟล์ในที่cacertsเก็บใบรับรองของ Java

keytool -import -v -trustcacerts -alias <your domain> -file ~/<your domain>.crt -keystore <JAVA HOME>/jre/lib/security/cacerts -keypass changeit -storepass changeit
  • แทนที่<your domain>ด้วยโดเมนของคุณ (เช่นjossef.com)
  • แทนที่<JAVA HOME>ด้วยโฮมไดเร็กทอรี Java ของคุณ

3) แฮ็คมัน

แม้ว่า iv'e จะติดตั้งใบรับรองของฉันในที่Javaเก็บใบรับรองเริ่มต้นTomcat ก็เพิกเฉยต่อ (ดูเหมือนว่าไม่ได้กำหนดค่าให้ใช้ที่เก็บใบรับรองเริ่มต้นของ Java)

หากต้องการแฮ็คนี้ให้เพิ่มสิ่งต่อไปนี้ในรหัสของคุณ:

String certificatesTrustStorePath = "<JAVA HOME>/jre/lib/security/cacerts";
System.setProperty("javax.net.ssl.trustStore", certificatesTrustStorePath);

// ...

4
ขั้นตอนที่ 2 ทำการหลอกลวงให้ฉันโดยใช้ SpringBoot และ Tomcat 7 ขอบคุณ
Tim Perry

ฉันต้องใช้ keytool จาก java ที่ใช้โดย Tomcat หรือไม่เพราะบนเซิร์ฟเวอร์เดียวฉันสามารถมี java
vikifor ได้

@vikifor ใช่ นอกจากนี้คุณยังสามารถเรียกใช้งานได้สำหรับทุกจาวาที่ติดตั้งบนระบบของคุณ
Jossef Harush

1
สิ่งนี้ได้ผล! ขอบคุณ ton @JossefHarush สำหรับคำตอบที่มีประโยชน์เช่นนี้!
Tom Taylor

1
ปัญหาของฉันได้รับการแก้ไขหลังจากเพิ่มส่วนรหัสของ @Jossef Harush ลงในรหัสของฉัน
Chamod Pathirana

10

ในกรณีของฉันปัญหาคือเว็บเซิร์ฟเวอร์ส่งใบรับรองและ CA ระดับกลางเท่านั้นไม่ใช่ root CA การเพิ่มตัวเลือก JVM นี้ช่วยแก้ปัญหา:-Dcom.sun.security.enableAIAcaIssuers=true

รองรับวิธีการเข้าถึง caIssuers ของส่วนเสริมสิทธิ์การเข้าถึงข้อมูลที่มีอยู่ มันถูกปิดการใช้งานโดยค่าเริ่มต้นสำหรับความเข้ากันได้และสามารถเปิดใช้งานได้โดยการตั้งค่าคุณสมบัติระบบcom.sun.security.enableAIAcaIssuersเป็นค่าจริง

หากตั้งค่าเป็นจริงการใช้ PKIX ของ CertPathBuilder ของ Sun จะใช้ข้อมูลในส่วนขยาย AIA ของใบรับรอง (นอกเหนือจาก CertStores ที่ระบุไว้) เพื่อค้นหาใบรับรอง CA ที่ออกให้ซึ่งเป็น URI ประเภท ldap, http หรือ ftp

แหล่ง


นี่แก้ปัญหาของฉันได้จริงขอบคุณ!
Luís Silva

6

เหตุผลอื่นอาจเป็น JDK รุ่นที่ล้าสมัย ฉันใช้ jdk รุ่น 1.8.0_60 เพียงอัปเดตเป็นเวอร์ชันล่าสุดแก้ไขปัญหาใบรับรอง


2
ฉันมีปัญหาเดียวกันด้วย การเรียกใช้ API ด้วย Lets Encrypt Certificate อาจไม่ทำงานกับ Java เวอร์ชันเก่ากว่าเพราะไม่ได้รับการยอมรับจากหน่วยงานผู้ออกใบรับรองรูทที่เชื่อถือได้ การอัปเดต Java จะแก้ปัญหานี้ได้
hertg

5

ไฟล์ cacerts ของฉันว่างเปล่าโดยสิ้นเชิง ฉันแก้ไขได้โดยการคัดลอกไฟล์ cacerts ออกจากเครื่อง windows ของฉัน (ที่ใช้ Oracle Java 7) และคัดลอกไปยังกล่อง Linux ของฉัน (OpenJDK)

cd %JAVA_HOME%/jre/lib/security/
scp cacerts mylinuxmachin:/tmp

และจากนั้นบนเครื่องลินุกซ์

cp /tmp/cacerts /etc/ssl/certs/java/cacerts

มันใช้งานได้ดีจนถึงตอนนี้


1
สิ่งนี้ใช้ได้ผลอย่างน่าอัศจรรย์หากปัญหาคือคุณกำลังใช้จาวารุ่นเก่าซึ่งไม่มีใบรับรองล่าสุด
atripathi

@atripathi แล้ว Mac ล่ะ
iOSAndroidWindowsMobileAppsDev

มีบางอย่างผิดปกติในการติดตั้ง Java ของคุณหากไฟล์ cacerts ว่างเปล่า คุณควรติดตั้งใหม่ทั้งหมด
มาร์ควิสแห่ง Lorne

บางที แต่วิธีนี้ใช้ได้ผลและไม่มีอะไรผิดปกติหลังจากนั้น
Ryan Shillington

5

สำหรับฉันข้อผิดพลาดนี้ปรากฏขึ้นในขณะที่พยายามเชื่อมต่อกับกระบวนการที่อยู่เบื้องหลังพร็อกซีย้อนกลับ NGINX ซึ่งกำลังจัดการ SSL

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

หวังว่านี่จะช่วยได้


นั่นคือสิ่งที่ฉันมี คุณช่วยอธิบายเกี่ยวกับวิธีเพิ่ม certs กลางและสถานที่ได้อย่างไร ฉันใช้ httpd reverse proxy ไม่ใช่ NGINX
Asaf Magen

สิ่งนี้ช่วยฉันในกรณีของฉันเพราะฉันใช้ httpd: access.redhat.com/solutions/43575
Asaf Magen

ด้วย nginx จะใช้ไฟล์. key และ. pem สำหรับ SSL config เท่านั้น ก่อนอื่นคุณต้องแปลง. crt เป็น. pem (เพียงแค่: cp yourfile.crt yourfile.pem) จากนั้นสำหรับ SSL cert chain: คุณต่อท้ายไฟล์. cer ไปที่. pem สุดท้าย (cat yourfile.cer >> yourfile.pem)
Thế Anh Nguyễn

5

การใช้ Tomcat 7 ภายใต้ Linux นี่เป็นการหลอกลวง

String certificatesTrustStorePath = "/etc/alternatives/jre/lib/security/cacerts";
System.setProperty("javax.net.ssl.trustStore", certificatesTrustStorePath);
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");

ภายใต้ Linux $JAVA_HOMEไม่ได้ตั้งค่าเสมอ แต่มักจะ/etc/alternatives/jreชี้ไปที่$JAVA_HOME/jre


5

รหัสด้านล่างใช้งานได้สำหรับฉัน:

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.X509TrustManager;

public class TrustAnyTrustManager implements X509TrustManager {

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

public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}

public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[] {};
}
}

HttpsURLConnection conn = null;
            URL url = new URL(serviceUrl);
            conn = (HttpsURLConnection) url.openConnection();
             SSLContext sc = SSLContext.getInstance("SSL");  
             sc.init(null, new TrustManager[]{new TrustAnyTrustManager()}, new java.security.SecureRandom());  

             conn.setSSLSocketFactory(sc.getSocketFactory());

5
รหัสนี้ไม่ปลอดภัยอย่างสมบูรณ์และไม่ควรใช้
มาร์ควิสแห่ง Lorne

@ user207421 ทำไมจึงไม่ปลอดภัย สิ่งที่เกิดขึ้นในรหัสสั้น ๆ
Govinda Sakhare

นี่เป็นการข้ามการตรวจสอบใบรับรองทั้งหมดโดยทั่วไปจะอนุญาตให้ใบรับรองใด ๆ ได้รับการยอมรับ วิธีการทำงานของ certs คือมีใบรับรอง root (ตามตัวอักษร) ที่ได้รับการปกป้องทางร่างกายที่หน่วยงานรับรองหลายแห่ง ใบรับรองนี้จะใช้ในการออกใบรับรองรองอื่น ๆ ซึ่งสามารถตรวจสอบได้ตลอดทางจนถึงสิทธิ์การรับรองรูท นี่เป็นการข้ามการตรวจสอบอัปสตรีมทั้งหมดซึ่งหมายความว่าฉันสามารถส่งใบรับรอง SSL (แม้แต่ที่สร้างขึ้นเอง) และใบสมัครของคุณจะยอมรับว่าปลอดภัยแม้ว่าตัวตนของฉันในฐานะ URL จะไม่ได้รับการยืนยัน
Scott Taylor

4

ฉันกำลังใช้jdk1.8.0_171เมื่อฉันประสบปัญหาเดียวกัน ฉันลองโซลูชัน 2 อันดับแรกที่นี่ (เพิ่มใบรับรองโดยใช้ keytool และโซลูชันอื่นซึ่งมีแฮ็กอยู่) แต่พวกเขาไม่ได้ผลสำหรับฉัน

ฉันอัพเกรด JDK เป็น1.8.0_181และมันทำงานได้อย่างมีเสน่ห์


2

ฉันเขียน win32 เล็ก ๆ (WinXP 32 บิต testet) stupid cmd (commandline) script ที่มองหาจาวาทุกเวอร์ชันในไฟล์โปรแกรมและเพิ่มใบรับรองให้พวกเขา รหัสผ่านจะต้องเป็น "เริ่มต้น" การเปลี่ยนแปลงเริ่มต้นหรือเปลี่ยนด้วยตัวคุณเองในสคริปต์ :-)

@echo off

for /F  %%d in ('dir /B %ProgramFiles%\java') do (
    %ProgramFiles%\Java\%%d\bin\keytool.exe -import -noprompt -trustcacerts -file some-exported-cert-saved-as.crt -keystore %ProgramFiles%\Java\%%d\lib\security\cacerts -storepass changeit
)

pause

2

สำหรับ MacOS X ด้านล่างนี้เป็นคำสั่งที่ใช้งานได้จริงสำหรับฉันโดยที่ฉันต้องลองสองครั้งในตัวเลือก 'importcert' ซึ่งใช้งานได้:

sudo keytool -–importcert -file /PathTo/YourCertFileDownloadedFromBrowserLockIcon.crt -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/security/cacerts -alias "Cert" -storepass changeit

2

สำหรับผมไม่ได้ทำงานการแก้ปัญหาที่ได้รับการยอมรับจากโพสต์นี้: https://stackoverflow.com/a/9619478/4507034

แต่ฉันจัดการเพื่อแก้ไขปัญหาโดยการนำเข้าใบรับรองไปยังการรับรองที่เชื่อถือได้ของเครื่องของฉัน

ขั้นตอน:

  1. ไปที่ URL (เช่น. https://localhost:8443/yourpath) ที่การรับรองไม่ทำงาน
  2. ส่งออกการรับรองตามที่อธิบายไว้ในโพสต์ดังกล่าว
  3. บนเครื่องที่เปิด windows: Manage computer certificates
  4. ไปที่Trusted Root Certification Authorities->Certificates
  5. นำเข้าyour_certification_name.cerไฟล์ ของคุณที่นี่

1

สำหรับ Tomcat ที่รันบนเซิร์ฟเวอร์ Ubuntu เพื่อค้นหาว่า Java กำลังใช้งานอยู่ให้ใช้คำสั่ง "ps -ef | grep tomcat":

ตัวอย่าง:

/home/mcp01$ **ps -ef |grep tomcat**
tomcat7  28477     1  0 10:59 ?        00:00:18 **/usr/local/java/jdk1.7.0_15/bin/java** -Djava.util.logging.config.file=/var/lib/tomcat7/conf/logging.properties -Djava.awt.headless=true -Xmx512m -XX:+UseConcMarkSweepGC -Djava.net.preferIPv4Stack=true -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=/usr/share/tomcat7/endorsed -classpath /usr/share/tomcat7/bin/bootstrap.jar:/usr/share/tomcat7/bin/tomcat-juli.jar -Dcatalina.base=/var/lib/tomcat7 -Dcatalina.home=/usr/share/tomcat7 -Djava.io.tmpdir=/tmp/tomcat7-tomcat7-tmp org.apache.catalina.startup.Bootstrap start
1005     28567 28131  0 11:34 pts/1    00:00:00 grep --color=auto tomcat

จากนั้นเราสามารถเข้าไปที่: cd /usr/local/java/jdk1.7.0_15/jre/lib/security

ไฟล์cacertsเริ่มต้นอยู่ที่นี่ ใส่ใบรับรองที่ไม่น่าเชื่อถือลงไป


1

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

  1. ดาวน์โหลดใบรับรองเว็บไซต์

  2. คัดลอกใบรับรอง (เช่น: cert_file.cer) ลงในไดเรกทอรี $ JAVA_HOME \ Jre \ Lib \ Security

  3. เปิด CMD ในผู้ดูแลระบบและเปลี่ยนไดเรกทอรีเป็น $ JAVA_HOME \ Jre \ Lib \ Security

  4. นำเข้าใบรับรองไปยังร้านค้าที่เชื่อถือได้โดยใช้คำสั่งด้านล่าง

keytool -import -alias ca -file cert_file.cer -keystore cacerts -passpass changeit

หากคุณมีข้อผิดพลาดที่บอกว่า keytool ไม่สามารถจดจำได้โปรด อ้างอิงสิ่งนี้

พิมพ์ใช่ชอบด้านล่าง

เชื่อถือใบรับรองนี้: [ใช่]

  1. ตอนนี้พยายามเรียกใช้รหัสของคุณหรือเข้าถึง URL โดยทางโปรแกรมโดยใช้ java

ปรับปรุง

หากเซิร์ฟเวอร์แอปของคุณเป็น jboss ให้ลองเพิ่มคุณสมบัติของระบบด้านล่าง

System.setProperty("org.jboss.security.ignoreHttpsHost","true");

หวังว่านี่จะช่วยได้!


1

โซลูชั่นที่ยืดหยุ่นได้ (Alpine Linux)

เพื่อให้สามารถแก้ไขปัญหานี้ได้ในสภาพแวดล้อมแอปพลิเคชันของเราเราได้เตรียมคำสั่งเทอร์มินัล Linux ดังนี้:

cd ~

จะสร้างไฟล์ใบรับรองในโฮมไดเร็กตอรี่

apk add openssl

คำสั่งนี้ติดตั้ง openssl ใน alpine Linux คุณสามารถค้นหาคำสั่งที่เหมาะสมสำหรับลีนุกซ์รุ่นอื่น ๆ

openssl s_client -connect <host-dns-ssl-belongs> < /dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > public.crt

สร้างไฟล์ใบรับรองที่ต้องการ

sudo $JAVA_HOME/bin/keytool -import -alias server_name -keystore $JAVA_HOME/lib/security/cacerts -file public.crt -storepass changeit -noprompt

นำไฟล์ที่สร้างไปใช้กับ JRE ด้วยโปรแกรม 'keytool'

หมายเหตุ:โปรดแทนที่ DNS ของคุณด้วย<host-dns-ssl-belongs>

Note2:โปรดทราบว่า-nopromptจะไม่แสดงข้อความยืนยัน (ใช่ / ไม่ใช่) และ-storepass changeitพารามิเตอร์จะปิดใช้งานการขอรหัสผ่านและให้รหัสผ่านที่จำเป็น (ค่าเริ่มต้นคือ 'เปลี่ยน') คุณสมบัติทั้งสองนี้จะช่วยให้คุณใช้สคริปต์เหล่านั้นในสภาพแวดล้อมแอปพลิเคชันของคุณเช่นการสร้างอิมเมจ Docker

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


0

ฉันมีปัญหานี้เช่นกัน

ฉันลองเกือบทุกอย่างด้วยการเพิ่มใบรับรอง SSL ไปยัง. keystore แต่มันไม่ทำงานกับ Java1_6_x สำหรับฉันมันช่วยได้ถ้าเราเริ่มใช้ Java เวอร์ชันใหม่กว่า, Java1_8_x เป็น JVM


1
เหมือนกับฉัน. การอัปเดตจาก Java 1.8.0_91 ถึง 1.8.0_121 แก้ปัญหาได้ ฉันได้รับข้อยกเว้นโดยใช้ Apache HTTPClient
Devabc

ฉันยังคงมีปัญหานี้โดยใช้การตรวจสอบสิทธิ์ Oauth2
Sofiane

0

ฉันมีปัญหากับ Android Studio ตอนที่ฉันอยู่หลังพรอกซี ฉันใช้ Crashlytics ที่พยายามอัปโหลดไฟล์การแมประหว่างบิลด์

ฉันเพิ่มใบรับรองพรอกซีที่ขาดหายไปใน truststore ซึ่งตั้งอยู่ที่ /Users/[username]/Documents/Android Studio.app/Contents/jre/jdk/Contents/Home/jre/lib/security/cacerts

ด้วยคำสั่งดังต่อไปนี้: keytool -import -trustcacerts -keystore cacerts -storepass [password] -noprompt -alias [alias] -file [my_certificate_location]

ตัวอย่างเช่นด้วยรหัสผ่าน truststore เริ่มต้น keytool -import -trustcacerts -keystore cacerts -storepass changeit -noprompt -alias myproxycert -file /Users/myname/Downloads/MyProxy.crt


0

แค่แฮ็คขนาดเล็ก อัปเดต URL ในไฟล์ "hudson.model.UpdateCenter.xml" จาก https เป็น http

<?xml version='1.1' encoding='UTF-8'?>
<sites>
  <site>
    <id>default</id>
    <url>http://updates.jenkins.io/update-center.json</url>
  </site>
</sites>

0

ฉันต้องการที่จะพูดสอดเพราะฉันมีสภาพแวดล้อม QEMU ที่ฉันต้องดาวน์โหลดไฟล์ในจาวา ปรากฎว่า/etc/ssl/certs/java/cacertsใน QEMU จะมีปัญหาเพราะมันไม่ตรงกับ/etc/ssl/certs/java/cacertsในสภาพแวดล้อมโฮสต์ สภาพแวดล้อมโฮสต์อยู่หลังพร็อกซี บริษัท ดังนั้น java cacerts เป็นเวอร์ชันที่กำหนดเอง

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

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

ทางออกที่ดีกว่าคือการติดตั้ง/etcลงในสภาพแวดล้อม QEMU อย่างไรก็ตามฉันไม่แน่ใจว่าไฟล์อื่นจะได้รับผลกระทบในกระบวนการนี้หรือไม่ ดังนั้นฉันตัดสินใจที่จะใช้สิ่งนี้น่าเกลียด แต่ง่ายต่อการแก้ไข


0

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

พิมพ์ดีดหมายความว่าฉันยังใช้ keystore เป็น truststore ด้วย เนื่องจาก บริษัท ของฉัน Root CA ไม่ได้ถูกกำหนดเป็นใบรับรองแบบสแตนด์อโลนในที่เก็บคีย์ แต่เป็นเพียงส่วนหนึ่งของเชนใบรับรองและไม่ได้กำหนดไว้ที่อื่น (เช่น cacerts) ฉันยังคงได้รับข้อผิดพลาด PKIX

หลังจากรีลีสที่ล้มเหลว (นี่คือการตั้งค่า prod มันก็โอเคที่อื่น) และการเกาหัวสองวันในที่สุดฉันก็เห็นการพิมพ์ผิดและตอนนี้ทุกอย่างดี

หวังว่านี่จะช่วยใครซักคน


-1

เพิ่มลงในรหัสของคุณ:

TrustManager[] trustAllCerts = new TrustManager[]{
           new X509TrustManager() {
               @Override
               public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                   return new X509Certificate[0];
               }

               @Override
               public void checkClientTrusted(
                       java.security.cert.X509Certificate[] certs, String authType) {
               }

               @Override
               public void checkServerTrusted(
                       java.security.cert.X509Certificate[] certs, String authType) {
               }
           }
       };

       try {
           SSLContext sc = SSLContext.getInstance("SSL");
           sc.init(null, trustAllCerts, new java.security.SecureRandom());
           HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
       } catch (GeneralSecurityException e) {
       }

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

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