2010-05-10 4 views
7

Benötigen Sie eine Anleitung.Java Webstart Truststore SSL

Ich habe Java Webstart App und ich möchte es mit einem Server über SSL verbinden.Nur eine Eigenschaft hinzufügen wie: System.setProperty ("javax.net.ssl.trustStore", "my.keystore"); Aber seit Ein JAWS-Programm wurde vom Server heruntergeladen und funktionierte nicht und hat keinen my.keystore im lokalen Dateisystem. Also beschlossen, das Zertifikat an alle Clients zu verteilen. Ich habe Folgendes getan und es hat funktioniert.

  1. Lesen Sie diesen Trust Store als Stream (verwenden Sie die getResourceAsStream-Methode).
  2. Speichern Sie es in einer beliebigen Datei auf dem Client-Rechner (sometemp)
  3. Aufruf System.setProperty ("javax.net.ssl.trustStore", trustStorePath);

Aber ich bin mir sicher, es muss bessere Lösungen als diese geben .. Irgendwelche Ideen, um es besser zu machen?

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 =========================== ** =========== ==

/** 

* */

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; 
     } 
} 

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]; 
    } 
} 

Laz Ihre Geduld zu schätzen wissen, versuchen zu lernen, wenn ich Zeit bekommen. Ich fing an, meine eigene CustomSSLSocketFactory zu schreiben..richtig jetzt umgehe ich die Sicherheit ... basierend auf dem Beispiel von Platin-Lösungen. Wenn ich das tue ... werden die Informationen als klarer Text im Netzwerk weitergegeben?

Jetzt frage ich mich, was soll ich tun mit der Truststore-Datei Ich habe "somestuststore.jks" -Datei. Was soll ich damit machen? Habe ich meine eigene benutzerdefinierte Trustmanager-Software? Bitte führen Sie mich in die richtige Richtung.

-padur

+0

Die Information wird kein Klartext sein. Es wird verschlüsselt, aber nicht authentifiziert, da dieser Code alle vertrauenswürdigen Zertifikate berücksichtigt. Sie müssen nicht Ihren eigenen Trustmanager schreiben, um die .jks-Datei zu bearbeiten. Sehen Sie sich meine Antwort unten an und stellen Sie fest, dass Sie eine KeyStore-Instanz an die SSLSocketFactory-Unterklasse weitergeben können. Sie können diese Instanz auf die gleiche Weise wie in Ihrem ursprünglichen Code abrufen, indem Sie aus dem Klassenpfad laden. – laz

Antwort

3

Sie es tun könnten, ohne auf Systemeigenschaften und das Dateisystem zu bauen. Wenn Sie den Keystore als Stream lesen, wie Sie es gerade tun, und Ihre eigene SSLSocketFactory erstellen, wäre dies viel sauberer.

Ich habe nicht verifiziert, aber ich sehe keinen Grund, warum dies nicht durch Webstart funktionieren sollte.

Aktualisiert:

Sie erwähnen, dass Sie Active Directory verbinden suchen, so vermute ich, Sie LDAPS als Protokoll verwenden werden? Wenn ja, kann der Code unter this URL als Inspiration dienen? Sie müssen eine Unterklasse von javax.net.ssl.SSLSocketFactory erstellen (siehe BlindSSLSocketFactoryTest bei dieser Platinumsolutions Link), die die obige Logik zum Erstellen der SSLContext umschließt und Anrufe an die SSLSocketFactory, die context.getSocketFactory() erstellt, delegiert.

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); 
    } 
} 

Hoffentlich kompiliert, ich kann es im Moment nicht testen! Beachten Sie auch die Faulheit mit der throws Klausel auf initTrustedSSLSocketFactory.

Dann, wenn Sie die LDAP-Umgebung-Setup, bei platinumsolutions

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

in ähnlicher Weise wie in dem Beispielcode verwenden. Hoffentlich ist das mehr von dem, was Sie suchen?

+0

Vielen Dank für die Lösung. Das letzte Mal habe ich die Frage nicht korrekt gestellt. Ich soll Verbindung zum Active Directory nicht HTTPS-Server herstellen und ich muss Benutzerinformationen überprüfen. In diesem Fall haben sie keine URL angegeben, sie haben mir ein Zertifikat als .jks Datei gegeben. Also HTTPURLConnection wird keine gute Idee, denke ich. Ich denke, nachdem ich den SSLContext erhalten habe, muss ich verschiedene API aufrufen, um es zu überprüfen. Bitte lassen Sie mich wissen, wenn Sie andere Ideen haben. -Padur – SPD

+0

Hallo Laz ... sorry reagiert spät. Ich verstehe, was Sie sagen wollen.Ich konnte nicht, was ist das Programm (Beispielcode bei Platinumsolutions) tun. Geht es um die Sicherheit? – SPD

+0

Ja, dieser Platinumsolutions-Code umgeht die Zertifikatsüberprüfung (siehe http://blog.platinumsolutions.com/node/79). Nimm es als Beispiel für das Konzept mehr als genau das, was du tun solltest. – laz

Verwandte Themen