15

我想通过 Java 连接到 Websphere 6.0 MQ。我已经为“正常”队列工作了代码,但现在我需要访问一个经过 SSL 加密的新队列(密钥库)。我收到了一个名为 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);
4

4 回答 4

14

developerWorks 中的 Alex Fehners 教程有点旧(2005 年),但有一些代码示例应该适合您。

Websphere MQ Java/JMS 客户端的 SSL 配置

您的 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 文件的人已经为此安排好了。

假设需要相互身份验证,那么除了 QMgr 的受信任证书之外,您的 jks 还将拥有一个代表您的应用程序的私有证书。要让应用程序获取证书并将其呈现给 QMgr,请使用-Djavax.net.ssl.keyStore=<location of keyStore>-Djavax.net.ssl.keyStorePassword=<password>参数。请注意,这些说密钥存储,而以前的参数说信任存储。

我的建议是与 WMQ 管理员一起设置和测试 SSL 连接。第一阶段应该是用 测试通道SSLCAUTH(OPTIONAL)。这验证了应用程序可以解析和验证 QMgr 的证书。只有当您完成这项工作时,WMQ 管理员才会更改SSLCAUTH(REQUIRED)反向测试身份验证的通道。

强烈建议您将 WMQ v7 客户端用于新应用程序。这有两个原因:1) v6 已于 2011 年 9 月终止;2) v7 代码内置了更多诊断功能。v7 客户端代码与 v6 QMgr 完全兼容,并且与 v6 客户端一样工作。您只是没有获得 v7 功能。在此处免费下载 WMQ 客户端代码:

IBM - MQC7:WebSphere MQ V7.0 客户端

我今年在 IMPACT 运行 WMQ 动手安全实验室,并将在周末在http://t-rob.net上发布脚本和实验室指南,所以请回来查看。

于 2010-04-22T20:24:35.293 回答
9

从 Oracle JVM (JSSE) 使用 SSL

另请参阅“从 Oracle Java(非 IBM JRE)连接到 MQ 队列管理器时支持哪些 TLS 密码规范/密码套件?

在 MQ 客户端版本 8.0.0.2 中包含一个补丁以将 TLS 与 Oracle JVM 一起使用,这适用于上面的通道答案

要让它工作,您将需要包含 IV66840的最新 MQ 客户端:WMQ V7 JAVA/JMS:在非 IBM JAVA 运行时环境中运行时添加对选定 TLS 密码规范的支持
http://www-01.ibm.com/support /docview.wss?uid=swg1IV66840
下载

根据您所在的位置,您可能还需要安装 Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 8(下载

要使用它,您必须使用 JVM 参数进行配置:

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

请注意,Oracle 和 IBM JVM 之间的默认安全实现行为不同:

Oracle JSSE 参考指南说:

如果 KeyManager[] 参数为 null,则将为该上下文定义一个空的 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());  

如果使用应用程序服务器,这可能由您的应用程序服务器处理。

于 2015-04-06T12:46:40.973 回答
5

试试这个代码以及关于证书的 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();
      }
   }
}
于 2014-09-18T07:18:47.717 回答
4

请注意您使用的是哪个 JRE。由于通往 IBM MQ 的 SSL 通道上存在某种加密 (TLS_RSA_WITH_AES_128_CBC_SHA),我们在使用 Sun JDK 时遇到了很大的麻烦。我们使用了 X509 证书。为了让它工作,我们使用 IBM JRE,因为它对某些密码套件有更大的支持!

于 2011-07-16T00:23:07.700 回答