HttpGet con HTTPS: SSLPeerUnverifiedException

Utilizzando HttpClient , ricevo il seguente errore quando tento di comunicare su HTTPS:

Eccezione nella discussione “main” javax.net.ssl.SSLPeerUnverifiedException: peer non autenticato.

Ecco il mio codice:

URI loginUri = new URI("https://myUrl.asp"); HttpClient httpclient = new DefaultHttpClient(); HttpGet httpget = new HttpGet( loginUri ); HttpResponse response = httpclient.execute( httpget ); 

Come posso sopprimere o rimuovere questo errore?

Nota: non farlo nel codice di produzione, utilizzare invece HTTP o la chiave pubblica autofirmata come suggerito sopra.

Su HttpClient 4.xx:

 import static org.junit.Assert.assertEquals; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.cert.X509Certificate; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.impl.client.DefaultHttpClient; import org.junit.Test; public class HttpClientTrustingAllCertsTest { @Test public void shouldAcceptUnsafeCerts() throws Exception { DefaultHttpClient httpclient = httpClientTrustingAllSSLCerts(); HttpGet httpGet = new HttpGet("https://host_with_self_signed_cert"); HttpResponse response = httpclient.execute( httpGet ); assertEquals("HTTP/1.1 200 OK", response.getStatusLine().toString()); } private DefaultHttpClient httpClientTrustingAllSSLCerts() throws NoSuchAlgorithmException, KeyManagementException { DefaultHttpClient httpclient = new DefaultHttpClient(); SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, getTrustingManager(), new java.security.SecureRandom()); SSLSocketFactory socketFactory = new SSLSocketFactory(sc); Scheme sch = new Scheme("https", 443, socketFactory); httpclient.getConnectionManager().getSchemeRegistry().register(sch); return httpclient; } private TrustManager[] getTrustingManager() { TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { @Override public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } @Override public void checkClientTrusted(X509Certificate[] certs, String authType) { // Do nothing } @Override public void checkServerTrusted(X509Certificate[] certs, String authType) { // Do nothing } } }; return trustAllCerts; } } 

Questa risposta segue le risposte di owlstead e Mat . Si applica alle installazioni SE / EE, non a ME / mobile / Android SSL.

Poiché nessuno lo ha ancora menzionato, menzionerò il “metodo di produzione” per risolvere il problema: Segui i passaggi della class AuthSSLProtocolSocketFactory in HttpClient per aggiornare il tuo negozio di fiducia e i tuoi keystore .

  1. Importa un certificato attendibile e genera un file truststore

keytool -import -alias "my server cert" -file server.crt -keystore my.truststore

  1. Genera una nuova chiave (usa la stessa password del truststore)

keytool -genkey -v -alias "my client key" -validity 365 -keystore my.keystore

  1. Emettere una richiesta di firma del certificato (CSR)

keytool -certreq -alias "my client key" -file mycertreq.csr -keystore my.keystore

  1. (autofirmare o far firmare il certificato)

  2. Importa il certificato radice della CA attendibile

keytool -import -alias "my trusted ca" -file caroot.crt -keystore my.keystore

  1. Importa il file PKCS # 7 che contiene la catena di certificati completa

keytool -import -alias "my client key" -file mycert.p7 -keystore my.keystore

  1. Verificare il contenuto del file keystore risultante

keytool -list -v -keystore my.keystore

Se non si dispone di un certificato del server, generarne uno in formato JKS, quindi esportarlo come file CRT. Fonte: documentazione keytool

 keytool -genkey -alias server-alias -keyalg RSA -keypass changeit -storepass changeit -keystore my.keystore keytool -export -alias server-alias -storepass changeit -file server.crt -keystore my.keystore 

Utilizzando HttpClient 3.x, è necessario eseguire questa operazione:

 Protocol easyHttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443); Protocol.registerProtocol("https", easyHttps); 

Una implementazione di EasySSLProtocolSocketFactory può essere trovata qui .

Questa eccezione verrà fornita nel caso in cui il server sia basato su JDK 7 e il client sia su JDK 6 e utilizzi certificati SSL. In JDK 7 sslv2hello l’handshake dei messaggi è disabilitato di default mentre in JDK 6 è abilitato l’handshaking dei messaggi sslv2hello. Per questo motivo, quando il tuo client tenta di connettere il server, un messaggio sslv2hello verrà inviato al server e, a causa della disabilitazione del messaggio sslv2hello, otterrai questa eccezione. Per risolvere questo devi spostare il tuo client su JDK 7 o devi usare la versione 6u91 di JDK. Ma per ottenere questa versione di JDK devi ottenere il

Metodo che restituisce un “secureClient” (in ambiente Java 7 – NetBeans IDE e GlassFish Server: porta https per impostazione predefinita 3920), spero che ciò possa aiutare:

 public DefaultHttpClient secureClient() { DefaultHttpClient httpclient = new DefaultHttpClient(); SSLSocketFactory sf; KeyStore trustStore; FileInputStream trustStream = null; File truststoreFile; // java.security.cert.PKIXParameters for the trustStore PKIXParameters pkixParamsTrust; KeyStore keyStore; FileInputStream keyStream = null; File keystoreFile; // java.security.cert.PKIXParameters for the keyStore PKIXParameters pkixParamsKey; try { trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); truststoreFile = new File(TRUSTSTORE_FILE); keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keystoreFile = new File(KEYSTORE_FILE); try { trustStream = new FileInputStream(truststoreFile); keyStream = new FileInputStream(keystoreFile); } catch (FileNotFoundException ex) { Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex); } try { trustStore.load(trustStream, PASSWORD.toCharArray()); keyStore.load(keyStream, PASSWORD.toCharArray()); } catch (IOException ex) { Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex); } catch (CertificateException ex) { Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex); } try { pkixParamsTrust = new PKIXParameters(trustStore); // accepts Server certificate generated with keytool and (auto) signed by SUN pkixParamsTrust.setPolicyQualifiersRejected(false); } catch (InvalidAlgorithmParameterException ex) { Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex); } try { pkixParamsKey = new PKIXParameters(keyStore); // accepts Client certificate generated with keytool and (auto) signed by SUN pkixParamsKey.setPolicyQualifiersRejected(false); } catch (InvalidAlgorithmParameterException ex) { Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex); } try { sf = new SSLSocketFactory(trustStore); ClientConnectionManager manager = httpclient.getConnectionManager(); manager.getSchemeRegistry().register(new Scheme("https", 3920, sf)); } catch (KeyManagementException ex) { Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex); } catch (UnrecoverableKeyException ex) { Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex); } } catch (NoSuchAlgorithmException ex) { Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex); } catch (KeyStoreException ex) { Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex); } // use the httpclient for any httpRequest return httpclient; }