Un modulo che sto aggiungendo alla nostra grande applicazione Java deve conversare con un sito Web protetto da SSL di un'altra società. Il problema è che il sito utilizza un certificato autofirmato. Ho una copia del certificato per verificare che non sto riscontrando un attacco man-in-the-middle e devo incorporare questo certificato nel nostro codice in modo tale che la connessione al server abbia esito positivo.
Ecco il codice di base:
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();
}
Senza alcuna gestione aggiuntiva in atto per il certificato autofirmato, questo si interrompe in conn.getOutputStream () con la seguente eccezione:
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
Idealmente, il mio codice deve insegnare a Java ad accettare questo certificato autofirmato, per questo punto nell'applicazione e da nessun'altra parte.
So che posso importare il certificato nell'archivio dell'autorità di certificazione di JRE e ciò consentirà a Java di accettarlo. Questo non è un approccio che voglio adottare se posso aiutare; sembra molto invasivo fare su tutte le macchine dei nostri clienti per un modulo che non possono usare; influenzerebbe tutte le altre applicazioni Java usando lo stesso JRE, e non mi piace, anche se le probabilità di qualsiasi altra applicazione Java che accede a questo sito sono nulle. Non è nemmeno un'operazione banale: su UNIX devo ottenere i diritti di accesso per modificare JRE in questo modo.
Ho anche visto che posso creare un'istanza di TrustManager che esegue alcuni controlli personalizzati. Sembra che potrei persino essere in grado di creare un TrustManager che deleghi al vero TrustManager in tutti i casi tranne questo certificato. Ma sembra che TrustManager venga installato a livello globale, e presumo influenzerebbe tutte le altre connessioni dalla nostra applicazione, e non ha nemmeno un buon odore per me.
Qual è il modo preferito, standard o migliore per configurare un'applicazione Java per accettare un certificato autofirmato? Posso raggiungere tutti gli obiettivi che ho in mente sopra, o dovrò scendere a compromessi? Esiste un'opzione che coinvolge file e directory e impostazioni di configurazione e un codice minimo o nullo?