2015-12-26 2 views
8

У меня есть этот простой JMX клиентЗаменить System.setProperty (....)

public void testTomcatBasicAuthentication() throws Exception 
    { 
     System.out.println("Test Server Basic Authentication"); 
     try 
     { 
      String truststore = "C:\\client.jks"; 
      String trustStorePassword = "password"; 

      JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://xxx.xxx.xxx.xxx:9999/jmxrmi"); 

      HashMap environment = new HashMap(); 
      String[] credentials = new String[] 
      { 
       "user", "passwd" 
      }; 
      environment.put(JMXConnector.CREDENTIALS, credentials); 
//   environment.put("javax.net.ssl.trustStore", truststore); 
//   environment.put("javax.net.ssl.trustStorePassword", trustStorePassword); 
//   environment.put("javax.net.ssl.keyStore", truststore); 
//   environment.put("javax.net.ssl.keyStorePassword", trustStorePassword); 

      KeyManager[] kms = getKeyManagers(truststore, trustStorePassword); 
      TrustManager[] tms = getTrustManagers(truststore, trustStorePassword); 

      System.setProperty("javax.net.ssl.trustStore", truststore); 
      System.setProperty("javax.net.ssl.trustStorePassword", trustStorePassword); 
      System.setProperty("javax.net.ssl.keyStore", truststore); 
      System.setProperty("javax.net.ssl.keyStorePassword", trustStorePassword); 

      JMXConnector jmxc = JMXConnectorFactory.connect(url, environment); 
      MBeanServerConnection server = jmxc.getMBeanServerConnection(); 

      Set<ObjectName> s2 = server.queryNames(new ObjectName("Catalina:type=Server,*"), null); 
      for (ObjectName obj : s2) 
      { 
       ObjectName objname = new ObjectName(obj.getCanonicalName()); 
       System.out.println("serverInfo " + server.getAttribute(objname, "serverInfo")); 
       System.out.println("address " + server.getAttribute(objname, "address")); 
       System.out.println("stateName " + server.getAttribute(objname, "stateName")); 
      } 
     } 
     catch (Exception e) 
     { 
      e.printStackTrace(); 
     } 
    } 

Как я могу заменить System.setProperty(....) с Java-код? Я не хочу использовать System.setProperty.

Редактировать. Я нашел это example

Можно ли использовать этот код?

KeyManager[] kms = getKeyManagers(truststore, trustStorePassword); 
      TrustManager[] tms = getTrustManagers(truststore, trustStorePassword); 
      SslContext.setCurrentSslContext(new SslContext(kms, tms, null)); 

private static TrustManager[] getTrustManagers(String location, String password) 
     throws IOException, GeneralSecurityException 
    { 
     // First, get the default TrustManagerFactory. 
     String alg = TrustManagerFactory.getDefaultAlgorithm(); 
     TrustManagerFactory tmFact = TrustManagerFactory.getInstance(alg); 

     FileInputStream fis = new FileInputStream(location); 
     KeyStore ks = KeyStore.getInstance("jks"); 
     ks.load(fis, password.toCharArray()); 
     fis.close(); 

     tmFact.init(ks); 

     // And now get the TrustManagers 
     TrustManager[] tms = tmFact.getTrustManagers(); 
     return tms; 
    } 

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

     FileInputStream fis = new FileInputStream(location); 
     KeyStore ks = KeyStore.getInstance("jks"); 
     ks.load(fis, password.toCharArray()); 
     fis.close(); 

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

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

    private static KeyStore keyStoreFromCertificateString(String alias, String certificateString) 
     throws NoSuchAlgorithmException, CertificateException, IOException, KeyStoreException 
    { 
     KeyStore ks = KeyStore.getInstance("jks"); 
     ks.load(null); // Create empty key store 
     CertificateFactory cf = CertificateFactory.getInstance("X.509"); 
     Certificate cert = cf.generateCertificate(new ByteArrayInputStream(certificateString.getBytes())); 
     ks.setEntry(alias, new KeyStore.TrustedCertificateEntry(cert), null); 
     return ks; 
    } 

Можете ли вы дать представление о том, как мы можем интегрировать этот код или должно быть какое-то другое решение?

+5

Что значит заменить? Что бы вы заменили? 'System.setProperty' * есть * Java-код –

+1

Я полагаю, что OP означает передать эти ключи/значения фабрике JMX без установки их по всей стране. –

+0

@ Gaël да, вы правы –

ответ

2

Я боюсь, что ваш вопрос не очень хорошо сформулирован. Я пишу, что хочу заменить System.setProperty, но для меня это похоже, на самом деле вы хотите использовать собственные магазины доверия/ключей.

Это было отвечено уже: Using a custom truststore in java as well as the default one

пример, что вы нашли это только половина решения. При создании соединений вы должны использовать соответствующих менеджеров. Что-то вроде этого:

sslContext.init(null, trustManagers, null); 
connection.setSSLSocketFactory(sslContext.getSocketFactory()); 

Источник: https://planet.jboss.org/post/creating_https_connection_without_javax_net_ssl_truststore_property

Но если вы не контролируете фактическое создание соединение, которое, вероятно, придется использовать глобальные свойства. (Или любой другой конфигурации механизм сервер приложений имеет)

+0

Не могли бы вы показать мне полный пример кода? –

6

Кажется, что это должно быть относительно легко, но это не так.

Необходимо указать классы заводских сокетов в окружающей среде, см. this example. Однако реализации, используемые в этом примере, используют фабрики сокетов jvm default. Вместо этого вам нужно настроить свои собственные экземпляры SSL*SocketFactory с соответствующим хранилищем ключей и хранилищем доверия. Затем вам нужно реализовать свои собственные экземпляры RMI*SocketFactory, используя сконфигурированные фабрики (-ы) сокета. Вы можете использовать jdk impls в качестве путеводителей, SslRMIClientSocketFactory и SslRMIServerSocketFactory.

+0

Мне удалось скопировать содержимое SslRMIClientSocketFactory и SslRMIServerSocketFactory. Что мне нужно добавить для реализации пользовательского RMI * SocketFactory? –

+0

P.S Кстати, есть ли другое альтернативное решение? Этот подход будет очень сложно реализовать? –

+0

@PeterPenzov - вы используете TrustManager и KeyManager для запуска SSLContext. вы используете [SSLContext] (https://docs.oracle.com/javase/6/docs/api/javax/net/ssl/SSLContext.html) для создания фабрик сокетов. есть много примеров этого онлайн. измените свои реализации фабрик сокетов rmi, чтобы использовать ваши фабрики сокетов ssl вместо экземпляров по умолчанию jvm. – jtahlborn

0

простой и легкий обходной путь, чтобы сделать эту работу, чтобы использовать отдельную копию системных свойств для каждого потока как объяснено очень хорошо в here (Интересно, что главный вопрос сам относится к той же проблеме, что и ваша). После этого установка keyStore и trustStore на свойства системы будет нить-локальным.

Убедитесь, что вы используете разные потоки для двух разных соединений ssl.