java - defaulthttpclient - set sslcontext httpclient
HttpGet con HTTPS: SSLPeerUnverifiedException (5)
Esta excepción vendrá en caso de que su servidor esté basado en JDK 7 y su cliente esté en JDK 6 y use certificados SSL. En JDK 7, el apretón de manos del mensaje sslv2hello está deshabilitado de forma predeterminada mientras que en JDK 6 sslv2hello se habilita el protocolo de enlace. Por este motivo, cuando su cliente intenta conectarse al servidor, se enviará un mensaje sslv2hello al servidor y, debido a la desactivación del mensaje sslv2hello, obtendrá esta excepción. Para resolver esto, debe mover su cliente a JDK 7 o tiene que usar la versión 6u91 de JDK. Pero para obtener esta versión de JDK debes obtener el
Usando HttpClient , recibo el siguiente error cuando intento comunicarme a través de HTTPS:
Excepción en el hilo "main" javax.net.ssl.SSLPeerUnverifiedException: peer no autenticado.
Aquí está mi código:
URI loginUri = new URI("https://myUrl.asp");
HttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet( loginUri );
HttpResponse response = httpclient.execute( httpget );
¿Cómo suprimo o elimino este error?
Esta respuesta sigue a owlstead y las respuestas de Mat . Se aplica a instalaciones SE / EE, no ME / mobile / Android SSL.
Como nadie lo ha mencionado aún, mencionaré la "forma de producción" para solucionarlo: siga los pasos de la clase AuthSSLProtocolSocketFactory en HttpClient para actualizar su tienda de confianza y almacenes de claves.
- Importe un certificado de confianza y genere un archivo de almacén de confianza
keytool -import -alias "my server cert" -file server.crt -keystore my.truststore
- Genera una nueva clave (usa la misma contraseña que el almacén de confianza)
keytool -genkey -v -alias "my client key" -validity 365 -keystore my.keystore
- Emita una solicitud de firma de certificado (CSR)
keytool -certreq -alias "my client key" -file mycertreq.csr -keystore my.keystore
(auto-firmar o obtener su certificado firmado)
Importe el certificado raíz de CA de confianza
keytool -import -alias "my trusted ca" -file caroot.crt -keystore my.keystore
- Importe el archivo PKCS # 7 que contiene la cadena de certificados completa
keytool -import -alias "my client key" -file mycert.p7 -keystore my.keystore
- Verificar los contenidos del archivo de keystore resultante
keytool -list -v -keystore my.keystore
Si no tiene un certificado de servidor, genere uno en formato JKS, luego expórtelo como un archivo CRT. Fuente: documentación de 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
Método que devuelve un "cliente seguro" (en un entorno Java 7 - NetBeans IDE y GlassFish Server: puerto https por defecto 3920), espero que esto pueda ayudar:
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;
}
Nota: No haga esto en el código de producción, use http en su lugar, o la clave pública autofirmada como se sugirió anteriormente.
En 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;
}
}
Usando HttpClient 3.x, necesita hacer esto:
Protocol easyHttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
Protocol.registerProtocol("https", easyHttps);
Una implementación de EasySSLProtocolSocketFactory se puede encontrar here .