โมดูลที่ฉันเพิ่มลงในแอปพลิเคชัน Java ขนาดใหญ่ของเราจะต้องสนทนากับเว็บไซต์ที่ปลอดภัย SSL ของ บริษัท อื่น ปัญหาคือเว็บไซต์ใช้ใบรับรองที่ลงนามด้วยตนเอง ฉันมีสำเนาใบรับรองเพื่อตรวจสอบว่าฉันไม่ได้พบกับการโจมตีจากคนกลางและฉันจำเป็นต้องรวมใบรับรองนี้เข้ากับรหัสของเราในลักษณะที่การเชื่อมต่อกับเซิร์ฟเวอร์จะประสบความสำเร็จ
นี่คือรหัสพื้นฐาน:
void sendRequest(String dataPacket) {
String urlStr = "https://host.example.com/";
URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setMethod("POST");
conn.setRequestProperty("Content-Length", data.length());
conn.setDoOutput(true);
OutputStreamWriter o = new OutputStreamWriter(conn.getOutputStream());
o.write(data);
o.flush();
}
หากไม่มีการจัดการเพิ่มเติมสำหรับใบรับรองที่ลงชื่อด้วยตนเองสิ่งนี้จะตายที่ conn.getOutputStream () โดยมีข้อยกเว้นต่อไปนี้:
Exception in thread "main" 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
....
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
....
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
ในทางที่ดีรหัสของฉันต้องสอนให้ Java ยอมรับใบรับรองนี้ด้วยตนเองหนึ่งใบรับรองสำหรับจุดนี้ในแอปพลิเคชันและไม่มีที่อื่นอีกแล้ว
ฉันรู้ว่าฉันสามารถนำเข้าใบรับรองไปยังที่จัดเก็บใบรับรองของ JRE และนั่นจะทำให้ Java ยอมรับได้ นั่นไม่ใช่วิธีที่ฉันต้องการหากฉันสามารถช่วยได้ ดูเหมือนว่าจะมีการรุกรานอย่างมากที่จะทำในเครื่องลูกค้าของเราทั้งหมดสำหรับหนึ่งโมดูลที่พวกเขาอาจไม่ได้ใช้ มันจะส่งผลกระทบต่อแอปพลิเคชัน Java อื่น ๆ ทั้งหมดที่ใช้ JRE เดียวกันและฉันไม่ชอบสิ่งนั้นแม้ว่าอัตราต่อรองของแอปพลิเคชัน Java อื่น ๆ ที่เคยเข้าถึงเว็บไซต์นี้จะไม่มีเลย มันไม่ได้เป็นการดำเนินการที่ไม่สำคัญ: ใน UNIX ฉันต้องได้รับสิทธิ์การเข้าถึงเพื่อแก้ไข JRE ด้วยวิธีนี้
ฉันเคยเห็นด้วยว่าฉันสามารถสร้างอินสแตนซ์ TrustManager ที่ทำการตรวจสอบที่กำหนดเองได้ ดูเหมือนว่าฉันอาจสามารถสร้าง TrustManager ที่มอบสิทธิ์ให้ TrustManager จริงในทุกกรณียกเว้นใบรับรองนี้ แต่ดูเหมือนว่า TrustManager จะได้รับการติดตั้งทั่วโลกและฉันเชื่อว่าจะมีผลกับการเชื่อมต่ออื่น ๆ ทั้งหมดจากแอปพลิเคชันของเรา
วิธีที่ต้องการมาตรฐานหรือวิธีที่ดีที่สุดในการตั้งค่าแอปพลิเคชัน Java เพื่อยอมรับใบรับรองแบบลงนามด้วยตนเองคืออะไร? ฉันสามารถบรรลุเป้าหมายทั้งหมดที่ฉันมีในใจข้างต้นหรือฉันจะต้องประนีประนอม? มีตัวเลือกที่เกี่ยวข้องกับไฟล์และไดเรกทอรีและการตั้งค่ากำหนดและรหัสน้อยถึงไม่มีหรือไม่