Un modulo che sto aggiungendo alla nostra grande applicazione Java deve dialogare con il sito Web protetto da SSL di un'altra azienda. Il problema è che il sito utilizza un certificato autofirmato. Ho una copia del certificato per verificare che non sto incontrando un attacco man-in-the-middle, e ho bisogno di incorporare questo certificato nel nostro codice in modo tale che la connessione al server abbia successo.Come posso utilizzare certificati diversi su connessioni specifiche?
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 ulteriori manipolazioni in atto per il certificato auto-firmato, questa muore a 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 posto nell'applicazione, e da nessun'altra parte.
So che posso importare il certificato nell'archivio dell'autorità di certificazione JRE e che consentirà a Java di accettarlo. Non è un approccio che voglio prendere se posso aiutare; sembra molto invasivo fare su tutte le macchine dei nostri clienti per un modulo che non possono usare; interesserebbe tutte le altre applicazioni Java che usano lo stesso JRE, e non mi piace, anche se le probabilità di qualsiasi altra applicazione Java che acceda a questo sito sono nulle. Non è nemmeno un'operazione banale: su UNIX devo ottenere i diritti di accesso per modificare il JRE in questo modo.
Ho anche visto che posso creare un'istanza di TrustManager che esegue un controllo personalizzato. Sembra che potrei anche essere in grado di creare un TrustManager che delega al vero TrustManager in tutte le istanze tranne questo certificato. Ma sembra che TrustManager venga installato a livello globale, e presumo che possa influire su tutte le altre connessioni dalla nostra applicazione, e che non abbia 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 devo scendere a compromessi? Esiste un'opzione che include file e directory e impostazioni di configurazione e un codice da zero a zero?
piccolo, soluzione di lavoro: http://www.rgagnon.com/javadetails/java-fix-certificate-problem-in-HTTPS.html –
@Hasenpriester: per favore non suggerire questa pagina. Disattiva la verifica di attendibilità. Non accetti solo il certificato autofirmato che desideri, ma accetta anche qualsiasi certificato con cui un aggressore MITM ti presenterà. – Bruno