2010-05-10 26 views
7

Cần một số hướng dẫn.Java Webstart Truststore SSL

Tôi có ứng dụng webstart java và tôi muốn nó kết nối với máy chủ qua SSL.just thêm thuộc tính như: System.setProperty ("javax.net.ssl.trustStore", "my.keystore"); một chương trình JAWS được tải xuống từ máy chủ không hoạt động và không có my.keystore trên hệ thống tệp cục bộ. Vì vậy, quyết định để phân phối chứng chỉ cho tất cả các khách hàng. Tôi đã làm như sau và nó đã làm việc.

  1. Đọc kho lưu trữ tin cậy này dưới dạng luồng (sử dụng phương thức getResourceAsStream).
  2. Lưu tệp vào bất kỳ tệp nào trên máy khách (sometemp)
  3. Gọi System.setProperty ("javax.net.ssl.trustStore", trustStorePath);

Nhưng tôi chắc chắn phải có giải pháp tốt hơn so với điều này .. Bất kỳ ý tưởng nào để làm cho nó tốt hơn?

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 đánh giá cao sự kiên nhẫn của bạn, cố gắng tìm hiểu khi tôi có chút thời gian. Tôi bắt đầu viết CustomSSLSocketFactory của riêng mình ... ngay bây giờ tôi đang bỏ qua bảo mật ... dựa trên ví dụ bằng giải pháp platinum.If tôi làm điều đó ... liệu thông tin có được chuyển thành văn bản rõ ràng trên mạng không?

Bây giờ tôi tự hỏi mình nên làm gì với tệp tin truststore Tôi đang gặp tệp "sometruststore.jks". Tôi nên làm gì với điều đó .. Tôi có wrie phần mềm tin cậy tùy chỉnh của riêng tôi? Vui lòng hướng dẫn tôi theo đúng hướng.

-padur

+0

Thông tin sẽ không rõ ràng. Nó sẽ được mã hóa, nhưng không được xác thực vì mã này xem xét tất cả các chứng chỉ được tin cậy. Bạn không phải viết người quản lý của riêng mình để xử lý tệp .jks. Hãy xem câu trả lời của tôi dưới đây và thấy rằng bạn có thể truyền một thể hiện KeyStore đến lớp con SSLSocketFactory. Bạn có thể lấy ví dụ đó giống như cách bạn đang ở trong mã ban đầu của bạn bằng cách tải nếu tắt của classpath. – laz

Trả lời

3

Bạn có thể làm điều đó mà không phải dựa vào thuộc tính hệ thống và hệ thống tệp. Đọc keystore như một dòng giống như bạn đang làm và tạo SSLSocketFactory của riêng bạn sẽ sạch hơn nhiều.

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

... 

Tôi chưa xác minh nhưng tôi không thấy lý do tại sao điều này không hoạt động thông qua Webstart.

Cập nhật:

Bạn đề cập rằng bạn đang tìm kiếm để kết nối vào thư mục hoạt động vì vậy tôi đoán bạn sẽ sử dụng LDAPS như giao thức? Nếu vậy, có thể mã ở số this URL có thể là nguồn cảm hứng? Bạn sẽ phải tạo một lớp con của javax.net.ssl.SSLSocketFactory (xem BlindSSLSocketFactoryTest tại liên kết platinumsolutions đó) kết thúc logic trên tạo SSLContext và ủy quyền các cuộc gọi đến SSLSocketFactory mà tạo ra context.getSocketFactory().

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

Hy vọng biên dịch đó, tôi không thể kiểm tra nó vào lúc này! Cũng lưu ý sự lười biếng với mệnh đề throws trên initTrustedSSLSocketFactory.

Sau đó, khi bạn cài đặt môi trường LDAP, sử dụng

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

trong một cách tương tự như các mẫu mã tại platinumsolutions. Hy vọng rằng đây là nhiều hơn những gì bạn đang tìm kiếm?

+0

Cảm ơn bạn đã cho giải pháp. Lần cuối tôi không hỏi chính xác câu hỏi. Tôi phải kết nối với thư mục hoạt động không phải là máy chủ HTTPS và tôi cần xác thực thông tin người dùng. Trong trường hợp này họ không cung cấp bất kỳ URL nào, họ đã cấp cho tôi chứng chỉ một tệp .jks. Vì vậy, HTTPURLConnection sẽ không phải là một ý tưởng tốt tôi nghĩ. Tôi đoán sau khi nhận được SSLContext tôi cần gọi API khác để xác minh. Vui lòng cho tôi biết nếu bạn có bất kỳ ý tưởng nào khác. -Padur – SPD

+0

Xin chào Laz..xin lỗi vì đã trả lời muộn. Tôi hiểu những gì bạn đang cố gắng nói. Tôi không thể có được chương trình (mẫu mã tại platinumsolutions) đang làm gì. Là nó bằng cách đi qua an ninh? – SPD

+0

Có, mã platinumsolutions đó đang bỏ qua xác thực chứng chỉ (xem http://blog.platinumsolutions.com/node/79). Lấy nó làm ví dụ về khái niệm nhiều hơn chính xác những gì bạn nên làm. – laz

Các vấn đề liên quan