Estoy usando Java 6 y estoy tratando de crear una HttpsURLConnection
contra un servidor remoto, usando un certificado de cliente.
El servidor utiliza un certificado raíz autofirmado y requiere que se presente un certificado de cliente protegido por contraseña. Agregué el certificado raíz del servidor y el certificado del cliente a un almacén de claves de Java predeterminado que encontré en /System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home/lib/security/cacerts
(OSX 10.5). ¿El nombre del archivo del almacén de claves parece sugerir que el certificado del cliente no debe entrar allí?
De todos modos, agregar el certificado raíz a esta tienda resolvió el infame javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed' problem.
Sin embargo, ahora estoy atascado en cómo usar el certificado de cliente. He intentado dos enfoques y ninguno me lleva a ninguna parte.
Primero, y preferido, intente:
SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
URL url = new URL("https://somehost.dk:3049");
HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
conn.setSSLSocketFactory(sslsocketfactory);
InputStream inputstream = conn.getInputStream();
// The last line fails, and gives:
// javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
Intenté omitir la clase HttpsURLConnection (no es ideal ya que quiero hablar HTTP con el servidor) y hago esto en su lugar:
SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket("somehost.dk", 3049);
InputStream inputstream = sslsocket.getInputStream();
// do anything with the inputstream results in:
// java.net.SocketTimeoutException: Read timed out
Ni siquiera estoy seguro de que el certificado de cliente sea el problema aquí.
Respuestas:
Finalmente lo resolvió;). Tengo una pista fuerte aquí (la respuesta de Gandalf también lo tocó un poco). Los enlaces faltantes fueron (en su mayoría) el primero de los parámetros a continuación, y hasta cierto punto pasé por alto la diferencia entre los almacenes de claves y los almacenes de confianza.
El certificado de servidor autofirmado debe importarse a un almacén de confianza:
Estas propiedades deben establecerse (ya sea en la línea de comandos o en el código):
Código de ejemplo de trabajo:
fuente
Si bien no se recomienda, también puede deshabilitar la validación del certificado SSL por completo:
fuente
¿Ha configurado las propiedades del sistema KeyStore y / o TrustStore?
o desde con el código
Lo mismo con javax.net.ssl.trustStore
fuente
Si está tratando con una llamada de servicio web utilizando el marco de Axis, hay una respuesta mucho más simple. Si todo lo que desea es que su cliente pueda llamar al servicio web SSL e ignorar los errores del certificado SSL, simplemente ponga esta declaración antes de invocar cualquier servicio web:
System.setProperty("axis.socketSecureFactory", "org.apache.axis.components.net.SunFakeTrustSocketFactory");
Se aplican las exenciones de responsabilidad habituales acerca de que esto es algo muy malo en un entorno de producción.
Encontré esto en la wiki de Axis .
fuente
Para mí, esto es lo que funcionó usando Apache HttpComponents ~ HttpClient 4.x:
El archivo P12 contiene el certificado de cliente y la clave privada del cliente, creada con BouncyCastle:
fuente
keyStore
es lo que contiene la clave privada y el certificado.Utilizo el paquete Apache commons HTTP Client para hacer esto en mi proyecto actual y funciona bien con SSL y un certificado autofirmado (después de instalarlo en cacerts como mencionaste). Échale un vistazo aquí:
http://hc.apache.org/httpclient-3.x/tutorial.html
http://hc.apache.org/httpclient-3.x/sslguide.html
fuente
SSLContext
directamente, por lo que puede configurar todo esto de esta manera, en lugar de usarAuthSSLProtocolSocketFactory
.Creo que tiene un problema con el certificado de su servidor, no es un certificado válido (creo que esto es lo que significa "handshake_failure" en este caso):
Importe su certificado de servidor a su almacén de claves trustcacerts en el JRE del cliente. Esto se hace fácilmente con keytool :
fuente
Usando el siguiente código
o
no es en absoluto necesario. Además, no es necesario crear su propia fábrica de SSL personalizada.
También encontré el mismo problema, en mi caso hubo un problema que completó la cadena de certificados no se importó a los almacenes de confianza. Importe certificados utilizando la utilidad keytool directamente desde el certificado raíz, también puede abrir el archivo cacerts en el bloc de notas y ver si la cadena de certificados completa se importa o no. Verifique el nombre de alias que proporcionó al importar certificados, abra los certificados y vea cuántos contiene, la misma cantidad de certificados debería estar en el archivo cacerts.
Además, el archivo cacerts debe configurarse en el servidor en el que está ejecutando su aplicación, los dos servidores se autenticarán entre sí con claves públicas / privadas.
fuente