2008-12-05 18 views
11

estoy tratando de hacer algo como¿Cómo usar un archivo en un contenedor como javax.net.ssl.keystore?

URL clientks = com.messaging.SubscriptionManager.class.getResource("client.ks"); 
String path = clientks.toURI().getPath(); 
System.setProperty("javax.net.ssl.keyStore", path); 

Dónde client.ks es un archivo almacenado en com/mensajería en el archivo JAR que estoy corriendo.

Lo que dice que javax.net.ssl.keyStore está esperando una ruta al archivo client.ks que está en el contenedor. Prefiero no extraer el archivo y ponerlo en la máquina del cliente si es posible. Entonces, ¿es posible hacer referencia a un archivo en un contenedor?

Esto no funciona, ya que getPath() devuelve nulo. Hay otra manera de hacer esto?

+0

El título es engañoso. Parece que está preguntando si puede obtener una referencia de archivo a un recurso en un archivo jar; la llamada a System.setProperty es irrelevante. –

Respuesta

25

Todavía estoy trabajando en la implementación, pero creo que es posible cargar el almacén de claves desde el contenedor a través de InputStream y establecer explícitamente el TrustStore programáticamente (frente a establecer las propiedades del sistema). Ver el artículo: Setting multiple truststore on the same JVM

¡Lo tengo trabajando!

InputStream keystoreInput = Thread.currentThread().getContextClassLoader() 
    .getResourceAsStream(<path in jar>/client.ks"); 
InputStream truststoreInput = Thread.currentThread().getContextClassLoader() 
    .getResourceAsStream(<path in jar>/client.ts"); 
setSSLFactories(keystoreInput, "password", truststoreInput); 
keystoreInput.close(); 
truststoreInput.close(); 

private static void setSSLFactories(InputStream keyStream, String keyStorePassword, 
    InputStream trustStream) throws Exception 
{  
    // Get keyStore 
    KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());  

    // if your store is password protected then declare it (it can be null however) 
    char[] keyPassword = keyStorePassword.toCharArray(); 

    // load the stream to your store 
    keyStore.load(keyStream, keyPassword); 

    // initialize a trust manager factory with the trusted store 
    KeyManagerFactory keyFactory = 
    KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());  
    keyFactory.init(keyStore, keyPassword); 

    // get the trust managers from the factory 
    KeyManager[] keyManagers = keyFactory.getKeyManagers(); 

    // Now get trustStore 
    KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());  

    // if your store is password protected then declare it (it can be null however) 
    //char[] trustPassword = password.toCharArray(); 

    // load the stream to your store 
    trustStore.load(trustStream, null); 

    // initialize a trust manager factory with the trusted store 
    TrustManagerFactory trustFactory = 
    TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());  
    trustFactory.init(trustStore); 

    // get the trust managers from the factory 
    TrustManager[] trustManagers = trustFactory.getTrustManagers(); 

    // initialize an ssl context to use these managers and set as default 
    SSLContext sslContext = SSLContext.getInstance("SSL"); 
    sslContext.init(keyManagers, trustManagers, null); 
    SSLContext.setDefault(sslContext);  
} 
+1

¡Gracias! He estado buscando la solución por un tiempo, y todas las otras cosas que he visto parecían demasiado complicadas :) – jeremija

+0

Buen trabajo, pero ten en cuenta que estás usando keyStorePassword dos veces. Como la contraseña del almacén de claves y la contraseña de clave privada, y ese no es siempre el caso. – muttonUp

+0

Agregué un nuevo parámetro, 'String keyPassphrase' y cambié una línea a keyFactory.init (keyStore, keyPassphrase.toCharArray()); – muttonUp

5

Puede obtener un InputStream en un recurso en un archivo jar, pero no en un File. Si la "cosa" que finalmente lee el almacén de claves espera un File o una ruta a un archivo, su única opción es extraerlo al sistema de archivos.

+0

Ok, gracias! Eso es lo que hice mientras tanto, y eso funciona bien; simplemente no es tan limpio. – darrickc

1

Aquí hay una versión limpia de user2529737's answer, en caso de que ayude. Ha eliminado la configuración innecesaria del almacén de confianza y añadido las importaciones necesarias, los parámetros para el tipo de almacén de claves y la contraseña de la clave.

import javax.net.ssl.HttpsURLConnection; 
import javax.net.ssl.KeyManager; 
import javax.net.ssl.KeyManagerFactory; 
import javax.net.ssl.SSLContext; 
import java.io.BufferedReader; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.net.URL; 
import java.security.KeyStore; 

public class PlainJavaHTTPS2Test { 

    public void setUp() throws Exception { 
     final String KEYSTOREPATH = "clientkeystore.p12"; // or .jks 

     // store password can be null if there is no password 
     final char[] KEYSTOREPASS = "keystorepass".toCharArray(); 

     // key password can be null if there is no password 
     final char[] KEYPASS = "keypass".toCharArray(); 

     try (InputStream storeStream = this.getClass().getResourceAsStream(KEYSTOREPATH)) { 
      setSSLFactories(storeStream, "PKCS12", KEYSTOREPASS, KEYPASS); 
     } 
    } 
    private static void setSSLFactories(InputStream keyStream, String keystoreType, char[] keyStorePassword, char[] keyPassword) throws Exception 
    { 
     KeyStore keyStore = KeyStore.getInstance(keystoreType); 

     keyStore.load(keyStream, keyStorePassword); 

     KeyManagerFactory keyFactory = 
       KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); 

     keyFactory.init(keyStore, keyPassword); 

     KeyManager[] keyManagers = keyFactory.getKeyManagers(); 

     SSLContext sslContext = SSLContext.getInstance("SSL"); 
     sslContext.init(keyManagers, null, null); 
     SSLContext.setDefault(sslContext); 
    } 
} 
+0

(Estaba pensando si debería hacer esto como una respuesta o no, pero al leer [esto ] (https://meta.stackoverflow.com/a/299524/365237), elegí tenerlo como propio) – eis

Cuestiones relacionadas