Modul yang saya tambahkan ke aplikasi Java kami yang besar harus berkomunikasi dengan situs web yang dilindungi SSL perusahaan lain. Masalahnya adalah bahwa situs tersebut menggunakan sertifikat yang ditandatangani sendiri. Saya memiliki salinan sertifikat untuk memverifikasi bahwa saya tidak menghadapi serangan manusia di tengah, dan saya perlu memasukkan sertifikat ini ke dalam kode kami sedemikian rupa sehingga koneksi ke server akan berhasil.
Berikut kode dasarnya:
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();
}
Tanpa ada penanganan tambahan di tempat untuk sertifikat yang ditandatangani sendiri, ini mati di conn.getOutputStream () dengan pengecualian berikut:
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
Idealnya, kode saya perlu mengajarkan Java untuk menerima sertifikat yang ditandatangani sendiri ini, untuk tempat ini dalam aplikasi, dan tidak di tempat lain.
Saya tahu bahwa saya dapat mengimpor sertifikat ke toko otoritas sertifikat JRE, dan itu akan memungkinkan Java untuk menerimanya. Itu bukan pendekatan yang ingin saya ambil jika saya bisa membantu; tampaknya sangat invasif untuk dilakukan pada semua mesin pelanggan kami untuk satu modul yang mungkin tidak mereka gunakan; itu akan mempengaruhi semua aplikasi Java lainnya menggunakan JRE yang sama, dan saya tidak suka itu meskipun kemungkinan aplikasi Java lain yang pernah mengakses situs ini adalah nol. Ini juga bukan operasi sepele: pada UNIX saya harus mendapatkan hak akses untuk memodifikasi JRE dengan cara ini.
Saya juga melihat bahwa saya dapat membuat instance TrustManager yang melakukan pengecekan khusus. Sepertinya saya bahkan dapat membuat TrustManager yang mendelegasikan ke TrustManager yang sebenarnya dalam semua hal kecuali sertifikat yang satu ini. Tetapi sepertinya TrustManager terinstal secara global, dan saya kira akan mempengaruhi semua koneksi lain dari aplikasi kita, dan itu juga tidak terasa benar bagi saya.
Apa yang disukai, standar, atau cara terbaik untuk mengatur aplikasi Java untuk menerima sertifikat yang ditandatangani sendiri? Dapatkah saya mencapai semua tujuan yang saya pikirkan di atas, atau apakah saya harus berkompromi? Apakah ada opsi yang melibatkan file dan direktori serta pengaturan konfigurasi, dan sedikit kode untuk tidak ada?