2012-07-31 46 views
17

Estoy construyendo un monitor de aplicación simple para sondear una de nuestras URL API y envíenos un correo electrónico si no puede obtener un código de estado HTTP 200 de la respuesta (esto indicaría nuestra API está fuera de servicio por alguna razón).Error SSL "Peer Not Authenticated" con HttpClient 4.1

estoy usando HttpClient 4.1 (esto es importante porque su API difiere en gran medida de 3.x).

Nuestro API es seguro SSL, sin embargo, entrar en:

http://example.com/our-api

en un navegador web que redirige a

https://example.com/our-api

sin causar ningún errores

Cuando HttpClient intenta golpear este URL (http://example.com/our-api), se produce un error con una excepción javax.net.ssl.SSLPeerUnverifiedException con un mensaje que indica:

pares no autenticado

veo que esto ocurra de una gran cantidad de otras personas como se evidencia en la publicación this (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é sucede esto en primer lugar. Entonces, en lugar de preguntar "¿cómo puedo arreglar esto?" Pensé que le preguntaría "¿Por qué sucede esto?" Antes de seguir adelante con una de las soluciones propuestas, me gustaría saber cuál es el problema que estoy tratando de arreglar ;-)

+1

Podría publicar la traza completa? –

+0

Debe tenerse en cuenta que este mensaje debe ser debido a programación extraña en HttpClient. Habría habido una falla anterior de SSLException 'handshake failure', y esto es lo que debería haber sido lanzado. Evidentemente, la ejecución continuó a una llamada SSLSession.getPeerCertificate(), que es la única API que arroja la excepción en el título. – EJP

Respuesta

24

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 AC conocida, esto sucede porque el conjunto de certificados CA disponibles para un navegador moderno es mucho más grande que el conjunto limitado que se envía con JDK/JRE.

La solución EasySSL que figura en uno de los mensajes 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.

+0

La mayoría de las veces el servidor SSL enviará la cadena pero sin incluir el certificado raíz. Por lo tanto, la mayoría de las veces no tendrá que importar toda la cadena al almacén de claves. Sin embargo, debes confiar explícitamente en el certificado raíz. –

+0

@owlstead sí, generalmente necesita importar solo la CA raíz; respuesta editada –

+0

Importé el certificado (versión de base64) en el almacén de claves en 'lib \ security \ cacerts', pero java aún muestra el mismo error. Cuando lo importé a la tienda de certificados de confianza de Windows, Chrome dejó de dar errores. Pero cuando lo hice con java keytool todavía no se puede conectar. – nurettin

6

Esto se produce cuando

... el par no era capaz de identificarse a sí mismo (por ejemplo, no hay ningún certificado , el conjunto de cifrado particular que se está utilizando no soporta la autenticación , o ninguna autenticación del mismo era establecido durante SSL handshaking) esta excepción se produce.

Probablemente la causa de esta excepción (donde está el stacktrace) 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 usando keytool que se envía con Java JDK. De lo contrario, tendrá que asignar otro almacén de confianza programáticamente.

0

No soy un desarrollador de Java pero estaba usando una aplicación de 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
0
keytool -import -v -alias cacerts -keystore cacerts.jks -storepass changeit -file C:\cacerts.cer 
Cuestiones relacionadas