2010-05-10 27 views
7

Bazı yönlendirme gerekiyor.Java Webstart Truststore SSL

java webstart uygulamasına sahibim ve SSL.just aracılığıyla bir sunucuya bağlanmasını istiyorum: System.setProperty ("javax.net.ssl.trustStore", "my.keystore"); Sunucudan bir JAWS programı indirildi ve yerel dosya sistemimde bir my.keystore yok. Bu yüzden sertifikayı tüm istemcilere dağıtmaya karar verdim. Takip ettim ve işe yaradı.

  1. Bu güven deposunu akış olarak okuyun (getResourceAsStream yöntemini kullanın).
  2. İstemci makinesindeki herhangi bir dosyaya kaydedin (sometemp)
  3. Call System.setProperty ("javax.net.ssl.trustStore", trustStorePath);

Ama bundan daha iyi çözümler olması gerektiğine eminim.

public boolean validateUserFromActiveDirectory(String userId) { 
        final String MEMBER_GROUP = "CN=asdadasd,OU=asdasdasd Accounts,OU=adasdas,OU=asdasdas,DC=asdasdas,DC=asdasdas,DC=adasdasd,DC=asdasdasd"; 
      String employeeNumber = ""; 
      final String LDAP_INIT_CTX = "com.sun.jndi.ldap.LdapCtxFactory"; 
      final String LDAP_URL = "ldap://xx-ssssssss.eee.eee.eeeee.eeeee:636"; 
      final String MY_ATTRS[] = { "employeeNumber" }; 
      String adminPassword = "somepassword"; 
      String securityProtocol = "ssl"; 
      boolean isValidUser = false; 
      try { 

        Hashtable env = new Hashtable(); 
        env.put(Context.INITIAL_CONTEXT_FACTORY, LDAP_INIT_CTX); 
        env.put(Context.PROVIDER_URL, LDAP_URL); 
        env.put(Context.SECURITY_AUTHENTICATION, "simple"); 
        env.put(Context.REFERRAL, "follow"); 
        env.put(Context.SECURITY_PRINCIPAL, MEMBER_GROUP); 
        env.put(Context.SECURITY_CREDENTIALS, adminPassword); 
        env.put(Context.SECURITY_PROTOCOL, securityProtocol); 

      //C:\Documents and Settings\yourusername\Local Settings\Temp 
      File tf = File.createTempFile("someTruststore", ".jks"); 
      tf.deleteOnExit(); 
      byte buffer[] = new byte[0x1000]; 
       ClassLoader cl = JNDI.class.getClassLoader(); 
      InputStream in = cl.getResourceAsStream(
        "someTruststore.jks"); 
      FileOutputStream out = new FileOutputStream(tf); 
      int cnt; 
      while ((cnt = in.read(buffer)) != -1) 
       out.write(buffer, 0, cnt); 
      in.close(); 
      out.close(); 
      System.setProperty("javax.net.ssl.trustStore", tf 
          .getAbsolutePath()); 

        DirContext context = new InitialLdapContext(env, null); 
        SearchControls searchControls = new SearchControls(); 
        searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); 
        NamingEnumeration results = context.search(
           "XX=ent,XX=abc,XX=aaaaa,XX=aaaa", "(sAMAccountName=" 
              + userId + ")", searchControls); 

        if (results != null && results.hasMore()) { 
         //some logic 

         } 
        } 
      } catch (Exception e) { 
        e.printStackTrace(); 
      } 
      return isValidUser; 
     } 

-Padur =========================== ** =========== öğrenmeye çalışıyorum */

Laz sabır için teşekkür ederiz
package util; 
import java.security.cert.X509Certificate; 

import javax.net.ssl.X509TrustManager; 

public class CustomTrustManager implements X509TrustManager { 

    public void checkClientTrusted(X509Certificate[] cert, String authType) { 
     return; 
    } 

    public void checkServerTrusted(X509Certificate[] cert, String authType) { 
     return; 
    } 

    public X509Certificate[] getAcceptedIssuers() { 
     return new X509Certificate[0]; 
    } 
} 

package util; 

/** 
* @author spaduri 
* 
*/ 
import java.io.IOException; 
import java.net.InetAddress; 
import java.net.Socket; 

import javax.net.SocketFactory; 
import javax.net.ssl.SSLContext; 
import javax.net.ssl.SSLSocketFactory; 
import javax.net.ssl.TrustManager; 

public class CustomSSLSocketFactory extends SSLSocketFactory { 

    private SSLSocketFactory factory; 

    public CustomSSLSocketFactory() { 
     try { 
      SSLContext sslcontext = null; 
       // Call getKeyManagers to get suitable key managers 
      KeyManager[] kms=getKeyManagers(); 
      if (sslcontext == null) { 
       sslcontext = SSLContext.getInstance("SSL"); 
       sslcontext.init(kms, 
       new TrustManager[] { new CustomTrustManager() }, 
       new java.security.SecureRandom()); 
      } 
      factory = (SSLSocketFactory) sslcontext.getSocketFactory(); 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } 
    } 


    public static SocketFactory getDefault() { 
     return new CustomSSLSocketFactory(); 
    } 

    public Socket createSocket(Socket socket, String s, int i, boolean flag) throws IOException { 
     return factory.createSocket(socket, s, i, flag); 
    } 

    public Socket createSocket(InetAddress inaddr, int i, InetAddress inaddr1, int j) throws IOException { 
     return factory.createSocket(inaddr, i, inaddr1, j); 
    } 

    public Socket createSocket(InetAddress inaddr, int i) throws IOException { 
     return factory.createSocket(inaddr, i); 
    } 

    public Socket createSocket(String s, int i, InetAddress inaddr, int j) throws IOException { 
     return factory.createSocket(s, i, inaddr, j); 
    } 

    public Socket createSocket(String s, int i) throws IOException { 
     return factory.createSocket(s, i); 
    } 

    public String[] getDefaultCipherSuites() { 
     return factory.getSupportedCipherSuites(); 
    } 

    public String[] getSupportedCipherSuites() { 
     return factory.getSupportedCipherSuites(); 
    } 

protected KeyManager[] getKeyManagers() 
     throws IOException, GeneralSecurityException 
     { 
     // First, get the default KeyManagerFactory. 
     String alg=KeyManagerFactory.getDefaultAlgorithm(); 
     KeyManagerFactory kmFact=KeyManagerFactory.getInstance(alg); 

     // Next, set up the KeyStore to use. We need to load the file into 
     // a KeyStore instance. 

     ClassLoader cl = CustomSSLSocketFactory.class.getClassLoader(); 
     // read the file someTrustStore from the jar file from a classpath 
     InputStream in = cl.getResourceAsStream("ssl/someTruststore.jks"); 
     //FileInputStream fis=new FileInputStream(adentTruststore.jks); 
     KeyStore ks=KeyStore.getInstance("jks"); 
     ks.load(in, null); 
     in.close(); 

     // Now we initialise the KeyManagerFactory with this KeyStore 
     kmFact.init(ks, null); 

     // And now get the KeyManagers 
     KeyManager[] kms=kmFact.getKeyManagers(); 
     return kms; 
     } 
} 

==

/** 

* , ne zaman biraz zaman al. Kendi CustomSSLSocketFactory'imi yazmaya başladım ... şimdi de güvenliği atladım ... platinyum çözümleri ile ilgili örneğe dayanarak. Bunu yaparsam bilgi ağda açık bir metin olarak geçecek mi?

Şimdi "sometruststore.jks" dosyasına sahip olduğunuz dosya deposu dosyasıyla ne yapmam gerektiğini merak ediyorum. Bununla ne yapmalıyım? Kendi özel güvenilir yazılımım olacak mı? Lütfen bana doğru yönde kılavuzluk edin.

+0

Bilgiler açık metin olmayacak. Bu kod şifrelenecek, ancak bu kodun güvenilir olması için tüm sertifikaları dikkate aldığından doğrulanmayacaktır. .jks dosyasını işlemek için kendi trustmanager'ınızı yazmanız gerekmez. Cevabımı aşağıya bir göz atın ve bir KeyStore örneğini SSLSocketFactory alt sınıfına iletebileceğinizi görün. Sınıf örneğini kapalı olarak yükleyerek bu kodu orijinal kodunuzda olduğu gibi alabilirsiniz. – laz

cevap

3

Sistem özellikleri ve dosya sistemine güvenmek zorunda kalmadan yapabileceğini -padur

. Anahtar deposunu, yaptığınız gibi bir akış olarak okumak ve kendi SSLSocketFactory'nizi oluşturmak çok daha temiz olacaktır.

import java.net.URL; 
import java.security.KeyStore; 
import java.security.SecureRandom; 

import javax.net.ssl.HttpsURLConnection; 
import javax.net.ssl.SSLContext; 
import javax.net.ssl.TrustManagerFactory; 

... 

    // assume keyStore is the KeyStore you read via getResourceAsStream 
    final TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509"); 
    trustManagerFactory.init(keyStore); 

    final SSLContext context = SSLContext.getInstance("SSL"); 
    context.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom()); 

    final URL url = new URL("https://whatever"); 
    final HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection(); 
    urlConnection.setSSLSocketFactory(context.getSocketFactory()); 

... 

Doğrulamadım ancak bunun neden Webstart üzerinden çalışmadığına dair bir neden göremiyorum.

Güncel:

Sen yüzden Protokol olarak LDAPS kullanacağız tahmin ediyorum etkin dizine bağlanmak isteyen söz? Eğer öyleyse, belki de this URL'daki kod ilham kaynağı olabilir? javax.net.ssl.SSLSocketFactory'un bir alt sınıfını oluşturmanız gerekir (bu platinumolutions bağlantısında BlindSSLSocketFactoryTest'a bakın) ve bu mantık SSLContext'u oluşturma mantığını sarar ve context.getSocketFactory()'un oluşturduğu SSLSocketFactory çağrılarını delegeler.

public class TrustedSSLSocketFactory extends SSLSocketFactory { 
    private static SSLContext context; 
    public static void initTrustedSSLSocketFactory(final KeyStore keyStore) throws Exception { 
     final TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509"); 
     trustManagerFactory.init(keyStore); 

     final SSLContext context = SSLContext.getInstance("SSL"); 
     context.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom()); 
    } 

    public static SocketFactory getDefault() { 
     return context.getSocketFactory(); 
    } 

    public Socket createSocket(String arg0, int arg1) throws IOException, UnknownHostException { 
     return trustedFactory.createSocket(arg0, arg1); 
    } 

    public Socket createSocket(InetAddress arg0, int arg1) throws IOException { 
     return trustedFactory.createSocket(arg0, arg1); 
    } 

    public Socket createSocket(String arg0, int arg1, InetAddress arg2, int arg3) throws IOException, UnknownHostException { 
     return trustedFactory.createSocket(arg0, arg1, arg2, arg3); 
    } 

    public Socket createSocket(InetAddress arg0, int arg1, InetAddress arg2, int arg3) throws IOException { 
     return trustedFactory.createSocket(arg0, arg1, arg2, arg3); 
    } 
} 

Bu derleme, şu anda test edemiyorum! Ayrıca initTrustedSSLSocketFactory numaralı telefondan throws maddesindeki tembelliği de dikkate alın.kurarken LDAP ortamı

Sonra platinumsolutions numune koduna benzer bir şekilde

TrustedSSLSocketFactory.initTrustedSSLSocketFactory(keyStore); 
env.put("java.naming.ldap.factory.socket", TrustedSSLSocketFactory.class.getName()) 

kullanın. Umarım bu aradığınız şeyden daha mı fazlası?

+0

Çözüm için teşekkür ederiz. Son kez soruyu doğru bir şekilde sormadım. HTTPS sunucusunun aktif dizinine bağlanmam gerekiyor ve kullanıcı bilgilerini doğrulamam gerekiyor. Bu durumda herhangi bir URL sağlamadılar, bana bir sertifika .jks dosyası verdiler. Yani HTTPURLConnection bence iyi bir fikir değil. SSLContext'i aldıktan sonra, bunu doğrulamak için farklı API'yi aramam gerekiyor. Başka bir fikriniz varsa lütfen bize bildirin. -Padur – SPD

+0

Merhaba Laz..sorry geç yanıt. Söylemeye çalıştığınız şeyi anlıyorum. Programın ne olduğunu anlayamadım (platinumolutions örnek kod). Güvenliği geçerek mi? – SPD

+0

Evet, bu platinumolutions kodu, sertifika doğrulamasını atlıyor (bkz. Http://blog.platinumsolutions.com/node/79). Kavramın bir örneği olarak, tam olarak ne yapmanız gerektiğinden fazlasını alın. – laz