使用SSL / Keystore连接到Java中的Websphere MQ

时间:2010-04-22 15:17:15

标签: ssl keystore ibm-mq

我想通过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 个答案:

答案 0 :(得分:11)

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

SSL configuration of the Websphere MQ Java/JMS client

您的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>参数。请注意这些 key 商店,而之前的parms说 trust 商店。

我的建议是与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 Clients

我今年在IMPACT运行WMQ实践安全实验室,并将在http://t-rob.net周末发布脚本和实验室指南,所以请检查一下。

答案 1 :(得分:8)

使用Oracle JVM(JSSE)中的SSL

另见&#34; What TLS cipherspecs/ciphersuites are supported when connecting from Oracle Java (non-IBM JRE) to MQ queue manager?&#34;

在MQ Client V8.0.0.2中,包含了一个补丁,用于将TLS与Oracle JVM一起使用,这适用于上面的lanes回答

要使其工作,您将需要包含的最新MQ客户端 IV66840:WMQ V7 JAVA / JMS:为选定的TLS CIPHERSPECS添加支持 在非IBM JAVA RUNTIME环境中运行 http://www-01.ibm.com/support/docview.wss?uid=swg1IV66840
download

根据您所在的位置,您可能还需要安装 Java密码术扩展(JCE)无限强度管辖权政策文件8(download

要使用此功能,必须使用JVM参数进行配置:

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

请注意Oracle和IBM JVM之间的默认安全实现行为differs

Oracle JSSE Reference guide说:

  

如果KeyManager []参数为null,则空KeyManager将为   为此背景定义。

IBM JSSE Reference guide说:

  

如果KeyManager []参数为null,则表示已安装的安全性   将搜索提供程序以获得最高优先级的实现   KeyManagerFactory,适当的KeyManager将从中   获得。

这意味着您必须设置your own ssl context

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

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

答案 2 :(得分: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();
      }
   }
}

答案 3 :(得分:3)

了解您正在使用的JRE。我们在使用Sun JDK时遇到了很大麻烦,因为在IBM MQ的SSL通道上有一定的加密(TLS_RSA_WITH_AES_128_CBC_SHA)。我们使用了X509证书。为了使其正常运行,我们正在使用IBM JRE,因为它对某些密码套件有更大的支持!