101 votos

¿Cómo se resuelve el error de Javax.net.ssl.SSLHandshakeException?

Me conecté con VPN para configurar la API de inventario para obtener la lista de productos y funciona bien. Una vez que obtengo el resultado del servicio web y me conecto a la interfaz de usuario. Y también integré PayPal con mi aplicación para hacer el pago exprés cuando hago una llamada de pago me enfrento a este error. Utilizo servlet para el proceso de back-end. ¿Puede alguien decir cómo solucionar este problema?

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: 
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target

152voto

Ryan Stewart Puntos 46960

Primero necesitas obtener el certificado público del servidor al que intentas conectarte. Eso puede hacerse de varias maneras, como contactando al administrador del servidor y pidiéndolo, usando openssl para descargarlo o, como parece ser un servidor HTTP, conectarse a él con cualquier navegador, ver la información de seguridad de la página y guardar una copia del certificado. (Google debería ser capaz de decirte exactamente qué hacer para tu navegador específico).

Ahora que tienes el certificado guardado en un archivo, necesitas añadirlo a la tienda de confianza de tu JVM. En $JAVA_HOME/jre/lib/security/ para JDKs o $JAVA_HOME/lib/security para JREs, hay un archivo llamado cacerts, que viene con Java y contiene los certificados públicos de las conocidas Autoridades de Certificación. Para importar el nuevo cert, ejecute keytool como un usuario que tenga permiso para escribir en cacerts:

keytool -import -file <the cert file> -alias <some meaningful name> -keystore <path to cacerts file>

Lo más probable es que le pida una contraseña. La contraseña por defecto que se envía con Java es "changeit". Casi nadie la cambia. Después de completar estos pasos relativamente sencillos, se comunicará de forma segura y con la seguridad de que está hablando con el servidor correcto y sólo con el servidor correcto (siempre y cuando no pierda su clave privada).

15voto

selladurai Puntos 2318

Ahora he resuelto este asunto de esta manera,

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.OutputStream; 

// Crear un administrador de confianza que no valide las cadenas de certificados como la predeterminada

            TrustManager[] trustAllCerts = new TrustManager[]{
                    new X509TrustManager() {

                        public java.security.cert.X509Certificate[] getAcceptedIssuers()
                        {
                            return null;
                        }
                        public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType)
                        {
                            //No need to implement.
                        }
                        public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)
                        {
                            //No need to implement.
                        }
                    }
            };

            // Install the all-trusting trust manager
            try 
            {
                SSLContext sc = SSLContext.getInstance("SSL");
                sc.init(null, trustAllCerts, new java.security.SecureRandom());
                HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
            } 
            catch (Exception e) 
            {
                System.out.println(e);
            }

Por supuesto, esta solución sólo debe utilizarse en los escenarios en los que no es posible instalar los certificados necesarios utilizando keytool por ejemplo, pruebas locales con certificados temporales.

12voto

Shree Puntos 176

Cada vez que intentamos conectarnos a la URL ,

Si el servidor del otro sitio funciona con el protocolo https y nos obliga a comunicarnos a través de la información proporcionada en el certificado, entonces tenemos la siguiente opción

1) Pedir el certificado (descargar el certificado), importar este certificado en fideicomiso. Los usos de java de trustore por defecto se pueden encontrar en \Java\jdk1.6.0_29\jre\lib\security\cacerts entonces si volvemos a intentar conectarnos a la conexión URL sería aceptado.

2) En casos normales de negocios podríamos estar conectando a URLS internos en las organizaciones y sabemos que son correctos. En tales casos, usted confía en que es la URL correcta. En tales casos, el código anterior puede ser usado, lo que no obligará a almacenar el certificado para conectarse a una URL en particular.

para el punto no 2 tenemos que seguir los siguientes pasos:

1) Escriba abajo el método que establece el verificador de nombre de host para la conexión Httpsur, el cual retorna verdadero para todos los casos, lo que significa que estamos confiando en el fideicomisario.

  // trusting all certificate 
 public void doTrustToCertificates() throws Exception {
        Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
        TrustManager[] trustAllCerts = new TrustManager[]{
                new X509TrustManager() {
                    public X509Certificate[] getAcceptedIssuers() {
                        return null;
                    }

                    public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
                        return;
                    }

                    public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {
                        return;
                    }
                }
        };

        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        HostnameVerifier hv = new HostnameVerifier() {
            public boolean verify(String urlHostName, SSLSession session) {
                if (!urlHostName.equalsIgnoreCase(session.getPeerHost())) {
                    System.out.println("Warning: URL host '" + urlHostName + "' is different to SSLSession host '" + session.getPeerHost() + "'.");
                }
                return true;
            }
        };
        HttpsURLConnection.setDefaultHostnameVerifier(hv);
    }

2) Escriba abajo el método, que llama a los Certificados de Confianza antes de intentar conectarse a la URL

    // connecting to URL
    public void connectToUrl(){
     doTrustToCertificates();//  
     URL url = new URL("https://www.abc.com");
     HttpURLConnection conn = (HttpURLConnection)url.openConnection(); 
     System.out.println("ResponseCoede ="+conn.getResponseCode());
   }

Esta llamada devolverá el código de respuesta = 200 significa que la conexión es exitosa.

para más detalles y ejemplo de muestra puede consultar URL

-1voto

Osama Javed Puntos 1039

Creo que estás tratando de conectarte a un algo usando SSL pero ese algo está proporcionando un certificado que no está verificado por las autoridades de certificación de root como verisign En esencia, por defecto, las conexiones seguras sólo pueden establecerse si la persona que intenta conectarse conoce las claves de las contrapartes o algún otro verndor como verisign puede intervenir y decir que la clave pública que se proporciona es realmente correcta

TODOS los OS confían en que un puñado de autoridades de certificación y pequeños emisores de certificados necesitan ser certificados por uno de los grandes certificadores que hacen una cadena de certificadores si entiendes lo que quiero decir...

De todos modos, volviendo al punto Tuve un problema similar al programar un applet de Java y un servidor de Java. (Con suerte, algún día escribiré un blog completo sobre cómo conseguí que funcionara toda la seguridad.) )

En esencia, lo que tuve que hacer fue extraer las claves públicas del servidor y almacenarlas en un almacén de claves dentro de mi applet y cuando me conecté al servidor usé este almacén de claves para crear una fábrica de confianza y esa fábrica de confianza para crear la conexión ssl. Hay procedimientos alternos como añadir la clave al host de confianza de la JVM y modificar el almacén de confianza por defecto en el inicio

Hice esto hace unos dos meses y no tengo el código fuente ahora mismo... usa Google y deberías ser capaz de resolver este problema. Si no puedes enviarme un mensaje y puedo proporcionarte el código fuente relevante para el proyecto ... No sé si esto resuelve tu problema, ya que no has proporcionado el código que causa estas excepciones. Además, yo estaba trabajando con applets y pensé que no podía ver por qué no funcionaría en los Serverlets...

P.D. No puedo obtener el código fuente antes del fin de semana ya que el SSH externo está desactivado en mi oficina.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X