Подтвердить что ты не робот

Подключение к WebSphere MQ в Java с помощью SSL/Keystore

Я хотел бы подключиться к WebSphere 6.0 MQ через Java. У меня уже работает код для "нормальной" очереди, но теперь мне нужно получить доступ к новой очереди, которая зашифрована SSL (keystore). Мне был отправлен файл под названием something.jks, который, как я полагаю, является сертификатом, который мне нужно хранить где-то. Я искал сеть, но я не могу найти нужную информацию.

Это код, который я использую для "нормальной" очереди. Я предполагаю, что мне нужно установить некоторое свойство, но не уверен, какой из них.

MQQueueConnectionFactory connectionFactory = new MQQueueConnectionFactory();
connectionFactory.setChannel(channel_);
connectionFactory.setHostName(hostname_);
connectionFactory.setPort(port_);
connectionFactory.setQueueManager(queueManager_);
connectionFactory.setTransportType(1);
connectionFactory.setSSsetSSLCertStores(arg0)

Connection connection = connectionFactory.createConnection();
connection.setExceptionListener(this);
session_ = connection.createSession(DEFAULT_TRANSACTED, DEFAULT_ACKMODE);
connection.start();

javax.jms.Queue fQueue = session_.createQueue(queue_);
consumer = session_.createConsumer(fQueue);
4b9b3361

Ответ 1

Учебник Alex Fehners в developerWorks немного устарел (2005), но имеет образцы кода, которые должны работать для вас.

Конфигурация SSL для клиента Java/JMS WebSphere MQ

Ваше приложение Java будет аутентифицировать QMgr на основе своего сертификата. Это означает, что файл jks, который вы предоставили, должен иметь либо самозаверяющий сертификат QMgr, либо иметь корневой сертификат центра сертификации, который подписал сертификат QMgr. В любом случае вы указываете файл с помощью -Djavax.net.ssl.trustStore=<location of trustStore>, как указано в статье, приведенной выше. Если у jks есть пароль, вам также нужно указать -Djavax.net.ssl.trustStorePassword=<password>. Аутентификация QMgr с доверительным магазином всегда требуется. Следующая часть может потребоваться или не понадобиться.

Другая часть головоломки заключается в том, что QMgr может потребовать, чтобы ваше приложение представляло сертификат. Другими словами, сертификат QMgr всегда аутентифицирован, независимо от того, требуется ли приложение для аутентификации, является необязательным. Если это так, то у вас есть так называемая "взаимная аутентификация". Если канал, с которым вы подключаетесь, был настроен с помощью SSLCAUTH(REQUIRED), тогда было включено взаимное аутентификация, и у QMgr должен быть собственный сертификат вашего приложения или корневой сертификат CA, который подписал ваш сертификат приложения в хранилище ключей. Надеюсь, кто-нибудь, кто настроит ваш файл jks, уложится для этого уже.

Предполагая, что требуется взаимное подтверждение, у ваших jks будет помимо доверенного сертификата QMgr частный сертификат, представляющий ваше приложение. Чтобы получить приложение для получения сертификата и представить его в QMgr, вы используете параметры -Djavax.net.ssl.keyStore=<location of keyStore> и -Djavax.net.ssl.keyStorePassword=<password>. Обратите внимание, что они говорят, что хранилище ключей, тогда как предыдущие parms сказали хранилище доверия.

Моя рекомендация - работать с администратором WMQ для настройки и тестирования SSL-соединения. Первый этап должен состоять в том, чтобы проверить канал с помощью SSLCAUTH(OPTIONAL). Это проверяет, может ли приложение разрешать и проверять подлинность сертификата QMgr. Только когда вы получите эту работу, администратор WMQ затем изменит канал на SSLCAUTH(REQUIRED), который проверяет аутентификацию в обратном направлении.

Я настоятельно рекомендую вам использовать клиент WMQ v7 для нового приложения. Это происходит по двум причинам: 1) v6 - конец жизни по состоянию на сентябрь 2011 года; 2) код v7 имеет гораздо больше возможностей для диагностики. Клиентский код v7 полностью совместим с v6 QMgr и работает как клиент v6. Вы просто не получаете функциональность v7. Загрузите код клиента WMQ здесь:

IBM - MQC7: Клиенты WebSphere MQ V7.0

В этом году я запускаю Лабораторию безопасности в режиме WMQ в IMPACT и выставляю сценарии и руководство по лабораторным работам в выходные дни http://t-rob.net, чтобы проверить это.

Ответ 2

Использование SSL из JVM Oracle (JSSE)

См. также " Какие TLS cipherspecs/ciphersuites поддерживаются при подключении от Oracle Java (не IBM JRE) к менеджеру очереди MQ?"

В MQ Client версии 8.0.0.2 включен патч для использования TLS с JVM Oracle, это работает с дорожками, чтобы ответить выше

Получите это для работы, вам понадобится последний MQ-клиент, который содержит IV66840: WMQ V7 JAVA/JMS: ДОБАВИТЬ ПОДДЕРЖКУ ДЛЯ ВЫБРАННЫХ ТЕЛЕФОНОВ CIPHERSPECS КОГДА РАБОТА В ОКРУЖАЮЩЕЙ СРЕДЕ JAVA RUNTIME NON-IBM
http://www-01.ibm.com/support/docview.wss?uid=swg1IV66840
(скачать)

В зависимости от вашего местоположения вам также может потребоваться установить Расширение Java Cryptography Extension (JCE) Неограниченное количество файлов политики юрисдикции 8 (download)

Чтобы использовать это, вам нужно настроить с помощью аргумента JVM:

  -Dcom.ibm.mq.cfg.useIBMCipherMappings=false

Обратите внимание, что поведение реализации безопасности по умолчанию отличается от между IBM и IBM JVM:

Справочник Oracle JSSE:

Если параметр KeyManager [] равен нулю, то пустой KeyManager будет для этого контекста.

Справочное руководство IBM JSSE:

Если параметр KeyManager [] равен нулю, установленная защита провайдеров будет искать самую высокоприоритетную реализацию KeyManagerFactory, из которого соответствующий KeyManager будет Полученный.

Это означает, что вам нужно настроить собственный контекст ssl

SSLContext  sslcontext = SSLContext.getInstance("TLS");
String  keyStore = System.getProperty("javax.net.ssl.keyStore");
String  keyStoreType = System.getProperty("javax.net.ssl.keyStoreType", KeyStore.getDefaultType());
String  keyStorePassword = System.getProperty("javax.net.ssl.keyStorePassword","");
KeyManager[]    kms = null;
if (keyStore != null)
{
    KeyManagerFactory   kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    KeyStore    ks = KeyStore.getInstance(keyStoreType);
    if (keyStore != null && !keyStore.equals("NONE")) {
        fs = new FileInputStream(keyStore);
    ks.load(fs, keyStorePassword.toCharArray());
    if (fs != null)
        fs.close();
    char[]  password = null;
    if (keyStorePassword.length() > 0)
        password = keyStorePassword.toCharArray();
    kmf.init(ks,password);
    kms = kmf.getKeyManagers();
}
sslcontext.init(kms,null,null);

И затем поставьте это клиенту MQ JMS:

    JmsConnectionFactory cf = ...                                                                     

    MQConnectionFactory mqcf = (MQConnectionFactory) cf;              
    mqcf.setSSLSocketFactory(sslcontext.getSocketFactory());  

При использовании сервера приложений это может обрабатываться вашим сервером приложений.

Ответ 3

Помните, какую JRE вы используете. У нас были большие проблемы с использованием Sun JDK из-за определенной криптографии (TLS_RSA_WITH_AES_128_CBC_SHA) на канале SSL в IBM MQ. Мы использовали X509 certeficate. Чтобы получить работу, мы используем IBM JRE, потому что она имеет гораздо большую поддержку определенных наборов шифров!

Ответ 4

Попробуйте этот код вместе с пояснениями T.Robs о сертификате:

import com.ibm.mq.jms.*;

import java.io.FileInputStream;
import java.io.Console;
import java.security.*;

import javax.jms.JMSException;
import javax.jms.QueueConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;

import com.ibm.mq.jms.MQQueueConnectionFactory;

public class SSLTest {

   public static void main(String[] args) {
      System.out.println(System.getProperty("java.home"));

      String HOSTNAME = "myhost";
      String QMGRNAME = "MyQMGR";
      String CHANNEL = "MY.SVRCONN";
      String SSLCIPHERSUITE = "TLS_RSA_WITH_AES_256_CBC_SHA";

      try {
         Class.forName("com.sun.net.ssl.internal.ssl.Provider");

         System.out.println("JSSE is installed correctly!");

         Console console = System.console();
         char[] KSPW = console.readPassword("Enter keystore password: ");

         // instantiate a KeyStore with type JKS
         KeyStore ks = KeyStore.getInstance("JKS");
         // load the contents of the KeyStore
         ks.load(new FileInputStream("/home/hudo/hugo.jks"), KSPW);
         System.out.println("Number of keys on JKS: "
               + Integer.toString(ks.size()));

         // Create a keystore object for the truststore
         KeyStore trustStore = KeyStore.getInstance("JKS");
         // Open our file and read the truststore (no password)
         trustStore.load(new FileInputStream("/home/xwgztu2/xwgztu2.jks"), null);

         // Create a default trust and key manager
         TrustManagerFactory trustManagerFactory =
           TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
         KeyManagerFactory keyManagerFactory =
           KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());

         // Initialise the managers
         trustManagerFactory.init(trustStore);
         keyManagerFactory.init(ks,KSPW);

         // Get an SSL context.
         // Note: not all providers support all CipherSuites. But the
         // "SSL_RSA_WITH_3DES_EDE_CBC_SHA" CipherSuite is supported on both SunJSSE
         // and IBMJSSE2 providers

         // Accessing available algorithm/protocol in the SunJSSE provider
         // see http://java.sun.com/javase/6/docs/technotes/guides/security/SunProviders.html
         SSLContext sslContext = SSLContext.getInstance("SSLv3");

         // Acessing available algorithm/protocol in the IBMJSSE2 provider
         // see http://www.ibm.com/developerworks/java/jdk/security/142/secguides/jsse2docs/JSSE2RefGuide.html
         // SSLContext sslContext = SSLContext.getInstance("SSL_TLS");
          System.out.println("SSLContext provider: " +
                            sslContext.getProvider().toString());

         // Initialise our SSL context from the key/trust managers
         sslContext.init(keyManagerFactory.getKeyManagers(),
                         trustManagerFactory.getTrustManagers(), null);

         // Get an SSLSocketFactory to pass to WMQ
         SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

         // Create default MQ connection factory
         MQQueueConnectionFactory factory = new MQQueueConnectionFactory();

         // Customize the factory
         factory.setSSLSocketFactory(sslSocketFactory);
         // Use javac SSLTest.java -Xlint:deprecation
         factory.setTransportType(JMSC.MQJMS_TP_CLIENT_MQ_TCPIP);
         factory.setQueueManager(QMGRNAME);
         factory.setHostName(HOSTNAME);
         factory.setChannel(CHANNEL);
         factory.setPort(1414);
         factory.setSSLFipsRequired(false);
         factory.setSSLCipherSuite(SSLCIPHERSUITE);

         QueueConnection connection = null;
         connection = factory.createQueueConnection("",""); //empty user, pass to avoid MQJMS2013 messages
         connection.start();
         System.out.println("JMS SSL client connection started!");
         connection.close();

      } catch (JMSException ex) {
         ex.printStackTrace();
      } catch (Exception ex){
         ex.printStackTrace();
      }
   }
}