java - example - Error "Peer no autenticado" de SSL con HttpClient 4.1
spring resttemplate https (4)
Estoy construyendo un monitor de aplicación simple para sondear una de nuestras URL de API y enviarnos un correo electrónico si no puede obtener un código de estado HTTP 200 de la respuesta (esto indicaría que nuestra API está inactiva por algún motivo).
Estoy usando HttpClient 4.1 (esto es importante porque su API difiere mucho de 3.x).
Nuestra API es segura con SSL, sin embargo, ingresando:
en un navegador web te redirige a
Sin causar ningún error.
Cuando HttpClient intenta presionar esta URL ( http://example.com/our-api
), falla con una excepción javax.net.ssl.SSLPeerUnverifiedException
con un mensaje que indica:
par no autenticado
Veo que esto está sucediendo mucho para otras personas, como lo demuestra este post (que también proporciona algunas formas de eludir este problema, una solución que voy a intentar implementar esta noche de hecho).
Lo que esta otra publicación (y las otras similares) no hacen es explicar por qué está sucediendo esto en primer lugar. Entonces, en lugar de preguntar "¿cómo puedo arreglar esto?" Pensé que me preguntaría " ¿por qué está pasando esto? " Antes de seguir adelante con una de las soluciones propuestas, me gustaría saber cuál es el problema que estoy tratando de solucionar ;-)
No soy un desarrollador de Java pero estaba usando una aplicación java para probar una API RESTful. Para que pueda corregir el error, tuve que instalar los certificados intermedios en el servidor web para que desapareciera el error. Estaba usando lighttpd, el certificado original se instaló en un servidor IIS. Espero eso ayude. Estos fueron los certificados que me faltaban en el servidor.
- CA.crt
- UTNAddTrustServer_CA.crt
- AddTrustExternalCARoot.crt
Esto se lanza cuando
... el par no fue capaz de identificarse a sí mismo (por ejemplo, ningún certificado, el conjunto de cifrado específico que se utiliza no admite la autenticación, o no se estableció ninguna autenticación entre pares durante el protocolo de enlace SSL) se lanza esta excepción.
Probablemente la causa de esta excepción (¿dónde está la pila de registros?) Le mostrará por qué se lanza esta excepción. Lo más probable es que el almacén de claves predeterminado incluido con Java no contenga (y confíe) el certificado raíz del TTP que se está utilizando.
La respuesta es recuperar el certificado raíz (por ejemplo, desde la conexión SSL de su navegador), importarlo en el archivo cacerts
y confiar en él mediante la keytool
que envía Java JDK. De lo contrario, tendrá que asignar otro almacén de confianza programáticamente.
Si el certificado del servidor es autofirmado, entonces está funcionando según lo diseñado y tendrá que importar el certificado del servidor a su almacén de claves.
Suponiendo que el certificado del servidor está firmado por una CA conocida, esto sucede porque el conjunto de certificados de CA disponibles para un navegador moderno es mucho más grande que el conjunto limitado que se envía con el JDK / JRE.
La solución EasySSL dada en una de las publicaciones que menciona simplemente oculta el error y no sabrá si el servidor tiene un certificado válido.
Debe importar la CA raíz apropiada en su almacén de claves para validar el certificado. Hay una razón por la que no puede evitar esto con el código stock de SSL, y eso es para evitar que escriba programas que se comporten como si fueran seguros pero no lo son.
keytool -import -v -alias cacerts -keystore cacerts.jks -storepass changeit -file C:/cacerts.cer