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

jav*_*ert 14 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);
Run Code Online (Sandbox Code Playgroud)

T.R*_*Rob 12

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>参数.注意这些说密钥库,而以前的parms说信任商店.

我的建议是与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上发布脚本和实验室指南,所以请检查一下.


olu*_*ies 8

使用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 RUNTIME环境中运行时为选定的TLS CIPHERSPECS添加支持
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
Run Code Online (Sandbox Code Playgroud)

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

甲骨文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);
Run Code Online (Sandbox Code Playgroud)

然后将其提供给MQ JMS客户端:

    JmsConnectionFactory cf = ...                                                                     

    MQConnectionFactory mqcf = (MQConnectionFactory) cf;              
    mqcf.setSSLSocketFactory(sslcontext.getSocketFactory());  
Run Code Online (Sandbox Code Playgroud)

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


小智 5

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


lan*_*nes 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();
      }
   }
}
Run Code Online (Sandbox Code Playgroud)