Cabe señalar que las respuestas a esta pregunta no hacen más de lo que se pregunta: le permiten ignorar el error pero no solucionan el problema subyacente (un poco como quitar las baterías de una alarma de humo en lugar de apagar el incendio) ) Los certificados tienen el propósito de garantizar la seguridad de la conexión SSL / TLS, ignorar esos errores introduce una vulnerabilidad al ataque MITM. Use certificados de prueba en lugar de ignorar el error.
"como quitar las baterías de una alarma de humo" Puede dar a otros desarrolladores el beneficio de la duda y asumir que saben lo que están haciendo. Quizás la motivación para esta pregunta son las pruebas locales y el OP desea realizar una prueba rápida sin pasar por las horribles cantidades de repeticiones de Java necesarias para configurar incluso un entorno SSL simple. Tal vez alguien podría responder la pregunta sin entrar en una conferencia "más sagrada que tú".
Mike
Es decir, en nuestra empresa, el servidor interno JIRA tiene un "certificado basado en la política de seguridad de Windows" que es válido en máquinas Windows incluidas en el dominio y no válido en otro. No puedo controlar esta política y todavía quiero llamar a JIRA REST API.
odiszapc
1
@Bruno La incapacidad de deshabilitar los detectores de humo durante un período de 30-60 minutos mientras se trata de un pequeño incendio en la cocina muestra una increíble falta de conocimiento sobre los patrones de uso por parte de algún funcionario legal en algún momento que siento que es ilegal. El hecho de que existe el concepto de "quitar las baterías de una alarma de humo" lo demuestra. Siento el mismo nivel de enojo por tener que obtener certificados para trabajar para una prueba simple que sé que no tiene ramificaciones de seguridad. La existencia de esta pregunta lo prueba.
Bill K
Respuestas:
84
Debe crear un SSLContext con su propio TrustManager y crear un esquema HTTPS utilizando este contexto. Aquí está el código
SSLContext sslContext =SSLContext.getInstance("SSL");// set up a TrustManager that trusts everything
sslContext.init(null,newTrustManager[]{new X509TrustManager(){public X509Certificate[] getAcceptedIssuers(){System.out.println("getAcceptedIssuers =============");returnnull;}publicvoid checkClientTrusted(X509Certificate[] certs,String authType){System.out.println("checkClientTrusted =============");}publicvoid checkServerTrusted(X509Certificate[] certs,String authType){System.out.println("checkServerTrusted =============");}}},newSecureRandom());SSLSocketFactory sf =newSSLSocketFactory(sslContext);Scheme httpsScheme =newScheme("https",443, sf);SchemeRegistry schemeRegistry =newSchemeRegistry();
schemeRegistry.register(httpsScheme);// apache HttpClient version >4.2 should use BasicClientConnectionManagerClientConnectionManager cm =newSingleClientConnManager(schemeRegistry);HttpClient httpClient =newDefaultHttpClient(cm);
Digamos que no quiero comprar un certificado SSL válido para mi sitio y solo quiero usarlo, ¿este código puede ayudar? ¿Cómo es que no veo ninguna parte donde se necesita una URL o se necesita un manejo de excepciones?
Vie
19
Hmm, me dice que 'new SSLSocketFactory (ssslCont)' espera un KeyStore, no un SSLContext. ¿Me estoy perdiendo de algo?
MSpeed
2
Recibo el error de que un X509TrustManager no se puede transmitir a un TrustManager.
MW.
2
Asegúrese de importar los paquetes correctos, es decir, desde org.apache.http.
Guardián
2
¿Alguien sabe cómo combinar todo esto usando HttpClientBuilder?
Ali
112
Todas las otras respuestas quedaron en desuso o no funcionaron para HttpClient 4.3.
Aquí hay una manera de permitir todos los nombres de host al crear un cliente http.
Gracias por la respuesta, me gustaría saber de qué paquete son HttpsClients, ya que estoy usando en la compilación de Android ("org.apache.httpcomponents: httpclient: 4.3.4") pero esta clase no aparece.
Juan Saravia
1
Su paquete es org.apache.http.impl.client.HttpClients.
erversteeg
14
Esto funciona alrededor de una falta de coincidencia del nombre de host (supongo), pero no parece funcionar cuando el certificado no está firmado por una autoridad confiable.
twm
1
@twm por eso dice que "permite todos los nombres de host", los problemas de confianza requieren una configuración diferente.
eis
1
@eis, estaba señalando que esta respuesta aborda la pregunta original en ciertos casos pero no en otros.
twm
43
Solo tuve que hacer esto con el HttpClient 4.5 más nuevo y parece que han dejado de usar algunas cosas desde 4.4, así que aquí está el fragmento que funciona para mí y utiliza la API más reciente:
¡Gracias! Simplemente cambie TrustAllStrategy.INSTANCEcon TrustSelfSignedStrategy.INSTANCEen esta respuesta.
Percy Vega
Esto no funcionó para mí. javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: error de construcción de ruta PKIX: sun.security. provider.certpath.SunCertPathBuilderException: no se puede encontrar la ruta de certificación válida para el objetivo solicitado
ggb667
26
Para el registro, probado con httpclient 4.3.6 y compatible con Executor de fluida api:
Para HttpClient 4.4 hacia arriba, debe hacer esto, y también puede necesitar crear un SSLConnectionSocketFactoryuso de eso SSLContexty definirlo en a Registry<ConnectionSocketFactory>, si va a crear un PoolingHttpClientConnectionManager. Las otras respuestas son más populares, pero no funcionan en HttpClient 4.4.
Thomas W
1
Funciona exactamente así con httpclient-4.3.5.jar.
Harald
18
Para Apache HttpClient 4.4:
HttpClientBuilder b =HttpClientBuilder.create();SSLContext sslContext =newSSLContextBuilder().loadTrustMaterial(null,newTrustStrategy(){publicboolean isTrusted(X509Certificate[] arg0,String arg1)throwsCertificateException{returntrue;}}).build();
b.setSslcontext( sslContext);// or SSLConnectionSocketFactory.getDefaultHostnameVerifier(), if you don't want to weakenHostnameVerifier hostnameVerifier =SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;SSLConnectionSocketFactory sslSocketFactory =newSSLConnectionSocketFactory(sslContext, hostnameVerifier);Registry<ConnectionSocketFactory> socketFactoryRegistry =RegistryBuilder.<ConnectionSocketFactory>create().register("http",PlainConnectionSocketFactory.getSocketFactory()).register("https", sslSocketFactory).build();// allows multi-threaded usePoolingHttpClientConnectionManager connMgr =newPoolingHttpClientConnectionManager( socketFactoryRegistry);
b.setConnectionManager( connMgr);HttpClient client = b.build();
Esto se extrae de nuestra implementación de trabajo real.
Las otras respuestas son populares, pero para HttpClient 4.4 no funcionan. Pasé horas probando y agotando las posibilidades, pero parece que hubo un cambio y reubicación de API extremadamente importante en 4.4.
El método sf.setHostnameVerifier ha quedado en desuso a partir de 4.1. La alternativa es usar uno de los constructores. Por ejemplo:SSLSocketFactory sf = new SSLSocketFactory(sslContext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
kaliatech
Esto fue muy útil cuando tuve que lidiar con el código heredado.
DuncanSungWKim
9
Estamos usando HTTPClient 4.3.5 y probamos que casi todas las soluciones existen en el stackoverflow pero nada. Después de pensar y resolver el problema, llegamos al siguiente código que funciona perfectamente, solo agrégalo antes de crear la instancia de HttpClient.
algún método para llamar al hacer solicitudes de publicación ...
Puede lograr lo mismo simplemente haciendosf.setHostnameVerifier(new AllowAllHostnameVerifier());
Dan Dyer,
77
El sf.setHostnameVerifier ha quedado en desuso a partir de 4.1. La alternativa es usar uno de los constructores. Por ejemplo:SSLSocketFactory sf = new SSLSocketFactory(sslContext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
kaliatech
4
DefaultHttpClient httpclient =newDefaultHttpClient();SSLContext sslContext;try{
sslContext =SSLContext.getInstance("SSL");// set up a TrustManager that trusts everythingtry{
sslContext.init(null,newTrustManager[]{new X509TrustManager(){public X509Certificate[] getAcceptedIssuers(){
log.debug("getAcceptedIssuers =============");returnnull;}publicvoid checkClientTrusted(
X509Certificate[] certs,String authType){
log.debug("checkClientTrusted =============");}publicvoid checkServerTrusted(
X509Certificate[] certs,String authType){
log.debug("checkServerTrusted =============");}}},newSecureRandom());}catch(KeyManagementException e){}SSLSocketFactory ssf =newSSLSocketFactory(sslContext,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);ClientConnectionManager ccm =this.httpclient.getConnectionManager();SchemeRegistry sr = ccm.getSchemeRegistry();
sr.register(newScheme("https",443, ssf));}catch(Exception e){
log.error(e.getMessage(),e);}
gracias por la respuesta actualizada, le di la recompensa al nuevo chico por ser "acogedor" ¡pero solo quería respuestas actualizadas para todos!
1
@feelingunwelcome, claro. También lo he votado a él :-)
Tarun Lalwani
2
una versión de trabajo completa para Apache HttpClient 4.1.3 (basado en el código de oleg anterior, pero aún necesitaba un allow_all_hostname_verifier en mi sistema):
Si encontró este problema al usar AmazonS3Client, que incorpora Apache HttpClient 4.1, simplemente necesita definir una propiedad del sistema como esta para que el comprobador de certificados SSL se relaje:
Si está utilizando Apache httpClient 4.5.x intente esto:
publicstaticvoid main(String... args){try(CloseableHttpClient httpclient = createAcceptSelfSignedCertificateClient()){HttpGet httpget =newHttpGet("https://example.com");System.out.println("Executing request "+ httpget.getRequestLine());
httpclient.execute(httpget);System.out.println("----------------------------------------");}catch(NoSuchAlgorithmException|KeyStoreException|KeyManagementException|IOException e){thrownewRuntimeException(e);}}privatestaticCloseableHttpClient createAcceptSelfSignedCertificateClient()throwsKeyManagementException,NoSuchAlgorithmException,KeyStoreException{// use the TrustSelfSignedStrategy to allow Self Signed CertificatesSSLContext sslContext =SSLContextBuilder.create().loadTrustMaterial(newTrustSelfSignedStrategy()).build();// we can optionally disable hostname verification. // if you don't want to further weaken the security, you don't have to include this.HostnameVerifier allowAllHosts =newNoopHostnameVerifier();// create an SSL Socket Factory to use the SSLContext with the trust self signed certificate strategy// and allow all hosts verifier.SSLConnectionSocketFactory connectionFactory =newSSLConnectionSocketFactory(sslContext, allowAllHosts);// finally create the HttpClient using HttpClient factory methods and assign the ssl socket factoryreturnHttpClients.custom().setSSLSocketFactory(connectionFactory).build();}
Respuestas:
Debe crear un SSLContext con su propio TrustManager y crear un esquema HTTPS utilizando este contexto. Aquí está el código
fuente
HttpClientBuilder
?Todas las otras respuestas quedaron en desuso o no funcionaron para HttpClient 4.3.
Aquí hay una manera de permitir todos los nombres de host al crear un cliente http.
O si está utilizando la versión 4.4 o posterior, la llamada actualizada se ve así:
fuente
Solo tuve que hacer esto con el HttpClient 4.5 más nuevo y parece que han dejado de usar algunas cosas desde 4.4, así que aquí está el fragmento que funciona para mí y utiliza la API más reciente:
fuente
Solo para el registro, hay una manera mucho más simple de lograr lo mismo con HttpClient 4.1
fuente
new SSLSocketFactory((chain, authType) -> true);
Apache HttpClient 4.5.5
No se ha utilizado ninguna API obsoleta.
Caso de prueba verificable simple:
fuente
TrustAllStrategy.INSTANCE
conTrustSelfSignedStrategy.INSTANCE
en esta respuesta.Para el registro, probado con httpclient 4.3.6 y compatible con Executor de fluida api:
fuente
SSLConnectionSocketFactory
uso de esoSSLContext
y definirlo en aRegistry<ConnectionSocketFactory>
, si va a crear unPoolingHttpClientConnectionManager
. Las otras respuestas son más populares, pero no funcionan en HttpClient 4.4.Para Apache HttpClient 4.4:
Esto se extrae de nuestra implementación de trabajo real.
Las otras respuestas son populares, pero para HttpClient 4.4 no funcionan. Pasé horas probando y agotando las posibilidades, pero parece que hubo un cambio y reubicación de API extremadamente importante en 4.4.
Consulte también una explicación un poco más completa en: http://literatejava.com/networks/ignore-ssl-certificate-errors-apache-httpclient-4-4/
¡Espero que ayude!
fuente
Si todo lo que quiere hacer es deshacerse de los errores de nombre de host no válidos, simplemente puede hacer:
fuente
SSLSocketFactory sf = new SSLSocketFactory(sslContext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
Estamos usando HTTPClient 4.3.5 y probamos que casi todas las soluciones existen en el stackoverflow pero nada. Después de pensar y resolver el problema, llegamos al siguiente código que funciona perfectamente, solo agrégalo antes de crear la instancia de HttpClient.
fuente
Con fluidez 4.5.2 tuve que hacer la siguiente modificación para que funcione.
fuente
Así es como lo hice.
Inicializando DefaultHTTPClient -
Simulacro de Fábrica SSL
Si está detrás de un proxy, debe hacer esto:
fuente
En extensión a la respuesta de ZZ Coder, será bueno anular el hostnameverifier.
fuente
sf.setHostnameVerifier(new AllowAllHostnameVerifier());
SSLSocketFactory sf = new SSLSocketFactory(sslContext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
fuente
Para aceptar todos los certificados en HttpClient 4.4.x, puede usar el siguiente revestimiento al crear el httpClient:
fuente
Probado con HttpClient 4.5.5 con Fluent API
fuente
El siguiente código funciona con
4.5.5
La salida del código es
La salida en el navegador es
El pom utilizado está debajo
fuente
una versión de trabajo completa para Apache HttpClient 4.1.3 (basado en el código de oleg anterior, pero aún necesitaba un allow_all_hostname_verifier en mi sistema):
Tenga en cuenta que vuelvo a lanzar todas las excepciones porque, en realidad, ¡no hay mucho que pueda hacer si algo de esto falla en un sistema real!
fuente
Si está utilizando la API fluida , debe configurarla a través de
Executor
:... donde
sslContext
se crea el SSLContext como se muestra en la respuesta del Codificador ZZ .Después de eso, puede hacer sus solicitudes http como:
Nota: probado con HttpClient 4.2
fuente
Probado con 4.3.3
}
fuente
Probado en 4.5.4:
fuente
Si encontró este problema al usar AmazonS3Client, que incorpora Apache HttpClient 4.1, simplemente necesita definir una propiedad del sistema como esta para que el comprobador de certificados SSL se relaje:
-Dcom.amazonaws.sdk.disableCertChecking = true
Travesura manejada
fuente
fwiw, un ejemplo que usa la implementación "RestEasy" de JAX-RS 2.x para construir un cliente especial "confíe en todos" ...
dependencias de Maven relacionadas
fuente
Si está utilizando Apache httpClient 4.5.x intente esto:
fuente