2010-09-09 13 views
7

En nuestra aplicación Java necesitamos comunicarnos con una lista de servidores en SSL utilizando el protocolo https. La lista de servidores para comunicarse cambiará en tiempo de ejecución. Inicialmente no tenemos ningún certificado del servidor. En tiempo de ejecución, obtendremos un nuevo certificado de servidor y agregaremos el certificado de clave pública a un almacén de confianza; y cualquier nueva conexión https con el servidor debería usar el almacén de confianza actualizado.Cómo soportar múltiples TrustStores en la aplicación de cliente java SSL

Estamos pensando en que debemos usar dos almacenes de confianza, uno de cacerts (uno por defecto enviado con jre) y otro que contiene certificados de los servidores que agregamos/eliminamos dinámicamente en una lista. Esto asegurará que no modifiquemos el TrustStore predeterminado (cacerts) de java.

Por favor, sugiera cómo se puede lograr esto. Además, ¿hay alguna forma de utilizar un almacén de confianza específico solo para un hilo en particular en Java, para que otros hilos (existentes y nuevos) aún utilicen el java trueststore predeterminado (cacerts) y un hilo específico use el truststore en particular? para el servidor.

Gracias, Deepak

Respuesta

5

Si desea importar el certificado de forma dinámica, es posible que necesite usar una costumbre x509TrustManager. Esto se hace al configurar el SSLContext, que se usa para crear el SSLSocketFactory o el SSLEngine.

jSSLutils es una biblioteca que le permite ajustar los administradores de confianza existentes y personalizar ciertas configuraciones. No lo necesitas, pero puede ser útil.

Esto iría a lo largo de estas líneas:

PKIXSSLContextFactory sslContextFactory = new PKIXSSLContextFactory(); 
sslContextFactory.setTrustManagerWrapper(new X509TrustManagerWrapper() { 
    @Override 
    public X509TrustManager wrapTrustManager(final X509TrustManager origManager) { 
     return new X509TrustManager() { 
      @Override 
      public X509Certificate[] getAcceptedIssuers() { 
       return origManager.getAcceptedIssuers(); 
      } 

      @Override 
      public void checkServerTrusted(X509Certificate[] chain, 
                String authType) 
        throws CertificateException { 
       try { 
        // This will call the default trust manager 
        // which will throw an exception if it doesn't know the certificate 
        origManager.checkServerTrusted(chain, authType); 
       } catch (CertificateException e) { 
        // If it throws an exception, check what this exception is 
        // the server certificate is in chain[0], you could 
        // implement a callback to the user to accept/refuse 
       } 
      } 

      @Override 
      public void checkClientTrusted(X509Certificate[] chain, 
                String authType) 
        throws CertificateException { 
       origManager.checkClientTrusted(chain, authType); 
      } 
     }; 
    } 
}); 
SSLContext sslContext = sslContextFactory.buildSSLContext(); 

(El (PKIX)SSLContextFactory y X509TrustManagerWrapper provienen de jSSLutils, pero el resto está disponible con el J2SE/J2EE.)

hay algunas CertificateExceptions que puede querer atrapar (ver subclases). Si realiza una devolución de llamada al usuario, es posible que la conexión SSL/TLS falle la primera vez debido a un tiempo de espera en el protocolo de enlace SSL/TLS (si la devolución de llamada tarda demasiado en ser respondida)

Podría usar este SSLContext como su predeterminado usando SSLContext.setSSLContext(...) (de Java 6), pero eso no es necesariamente una buena idea. Si puede, pase el SSLContext a la biblioteca que hace la conexión SSL/TLS. Cómo se hace esto varía, pero Apache HTTP Client 4.x, por ejemplo, tiene múltiples opciones para configurar su configuración SSL, una de ellas es pasando KeyStore s, otra al pasar SSLContext.

También podría hacer algo por hilo en lugar de por objeto que se va a conectar (dependiente de la biblioteca), verificando el hilo actual dentro del X509TrustManager: esto probablemente haría las cosas un poco más complejas en términos de sincronización y gestión de hilos/"conciencia" por el administrador de confianza.

+0

Me funcionó ... Gracias – Nayeem

2

Esta pregunta es tan viejo que tengo mis dudas mi granito de arena ayudará a cualquier persona, pero aquí va ...

Si se quiere resolver un problema (creador original) de la OP sin recurrir a cambios en el código puede configurar su JVM (solo probé con Tomcat) para admitir la configuración deseada del OP: 1. dejar solo el archivo 'camerts' JDK cacerts 2.importa tus certs en un archivo separado y haz que tus aplicaciones JAVA 'confíen en ellos'

Solía ​​importar mi certificado adicional en un archivo separado y luego consultarlo en mi inicio de JVM con el parámetro '-Djavax.net.ssl .trustStore = $ JAVA_HOME/jre/lib/security/jssecacerts 'con gran éxito, pero creo que los recientes (algo) problemas de seguridad de JAVA cambiaron una inclusión automatizada del archivo cacerts distribuido con el SDK.

así que encontré una solución ingeniosa Uso de Intel de este post y las estas páginas (con algunos cambios de menor importancia): - http://www.coderanch.com/t/529157/Tomcat/Configure-Tomcat-trust-store-cacerts - http://andyarismendi.blogspot.com/2012/01/changing-tomcats-ca-trust-keystore-file.html

Lo que solía hacer: - establecer el parámetro JVM trustStore a mi archivo de almacén de claves aparte (que me gustaría importar los CERT adicionales a) de la siguiente manera

lo que hago ahora: - Ajuste el parámetro trustStore a la 'empaquetado' cacerts presentar - Ajuste el parámetro keyStore a mis certs 'adicionales' archivo - Establecer el ke yStorePassword parámetro de la contraseña de mi almacén de claves (por defecto es changeit)

Lo que parece:

-Djavax.net.ssl.trustStore=$JAVA_HOME/jre/lib/security/cacerts \ 
-Djavax.net.ssl.keyStore=$JAVA_HOME/jre/lib/security/jssecacerts \ 
-Djavax.net.ssl.keyStorePassword="changeit" \ 

la esperanza que esto sea útil a alguien. No estoy al 100% que necesite especificar la contraseña de keyStore ya que no lo hace con el trustStore, pero funciona cuando lo hace.

+1

La pregunta era acerca de hacer esto para un hilo/conexión en particular, mientras que establecer 'javax.net.ssl.trustStore' afectará todas las conexiones (excepto aquellas que tienen su' SSLContext' específico) . Además, no hay ningún punto de configuración 'javax.net.ssl.keyStore *' en este caso (y 'jssecacerts' no debe contener ninguna clave privada, por lo que será inútil como un" almacén de claves "de todos modos). – Bruno

Cuestiones relacionadas