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

发布于 2024-08-30 01:58:01 字数 843 浏览 4 评论 0原文

我想通过 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);

I'd like to connect to a Websphere 6.0 MQ via Java. I have already working code for a "normal" queue, but now I need to access a new queue which is SSL encrypted (keystore). I have been sent a file called something.jks, which I assume is a certificate I need to store somewhere. I have been searching the net, but I can't find the right information.

This is the code I use for the "normal" queue. I assume I need to set some property, but not sure which one.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

梦罢 2024-09-06 01:58:01

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

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

Java 应用程序将根据其证书对 QMgr 进行身份验证。这意味着您提供的 jks 文件必须具有 QMgr 的自签名证书,或者具有签署 QMgr 证书的证书颁发机构的根证书。无论哪种情况,您都可以使用 -Djavax.net.ssl.trustStore= 指向该文件,如上面链接的文章中所述。如果 jks 有密码,您还需要指定 -Djavax.net.ssl.trustStorePassword=始终需要使用信任库对 QMgr 进行身份验证。下一部分可能需要也可能不需要。

另一个难题是 QMgr 可能要求您的应用程序提供证书。换句话说,QMgr 证书始终经过身份验证,应用程序是否需要进行身份验证是可选的。如果是,那么您就拥有了所谓的“相互身份验证”。如果您连接到的通道已配置 SSLCAUTH(REQUIRED),则已启用相互身份验证,并且 QMgr 必须拥有您的应用程序的自签名证书或签署您的应用程序证书的 CA 根证书它的密钥库。希望设置你的 jks 文件的人已经为此做好了安排。

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

我的建议是与 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,请回来查看。

Alex Fehners tutorial in developerWorks is a bit old (2005) but has code samples that should work for you.

SSL configuration of the Websphere MQ Java/JMS client

Your Java app will authenticate the QMgr based on its certificate. That means the jks file you were provided must have either the QMgr's self-signed certificate or it will have the root certificate of a Certificate Authority that signed the QMgr's certificate. In either case you point to the file using the -Djavax.net.ssl.trustStore=<location of trustStore> as noted in the article linked above. If the jks has a password, you will need to specify -Djavax.net.ssl.trustStorePassword=<password> as well. Authenticating the QMgr with a truststore is always required. The next part may or may not be required.

The other piece of the puzzle is that the QMgr may require your app to present a certificate. In other words, the QMgr cert is always authenticated, whether the app is required to authenticate is optional. If it is then you have what is known as "mutual authentication". If the channel that you connect to has been configured with SSLCAUTH(REQUIRED) then mutual auth has been enabled and the QMgr must have your application's self-signed cert or a CA root cert that signed your app's cert in its keystore. Hopefully whoever set up your jks file will have arranged for this already.

Assuming mutual auth is required, then your jks will have, in addition to the QMgr's trusted cert, a private cert representing your application. To get the app to fetch the cert and present it to the QMgr, you use the -Djavax.net.ssl.keyStore=<location of keyStore> and -Djavax.net.ssl.keyStorePassword=<password> parameters. Note these say key store whereas the previous parms said trust store.

My recommendation is to work with the WMQ administrator to set up and test the SSL connection. The first phase should be to test the channel with SSLCAUTH(OPTIONAL). This verifies that the application can resolve and authenticate the QMgr's certificate. Only when you get this working would the WMQ admin then change the channel to SSLCAUTH(REQUIRED) which tests authentication in the reverse direction.

I would highly recommend that you use the WMQ v7 client for a new application. This is for two reasons: 1) v6 is end-of-life as of Sept 2011; 2) the v7 code has a lot more diagnostic capability built in. The v7 client code is completely compatible with a v6 QMgr and works like the v6 client. You just don't get the v7 functionality. Download the WMQ client code free here:

IBM - MQC7: WebSphere MQ V7.0 Clients

I'm running the WMQ Hands-On Security Lab at IMPACT this year and will be posting the scripts and lab guide over the weekend at http://t-rob.net so check back for that.

离鸿 2024-09-06 01:58:01

从 Oracle JVM (JSSE) 使用 SSL

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

在 MQ 客户端版本 8.0.0.2 中包含一个用于使用 TLS 的补丁对于 Oracle JVM,这适用于上面的 lanes 答案

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

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

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

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

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

Oracle JSSE 参考指南 说:

如果 KeyManager[] 参数为 null,则将生成一个空的 KeyManager
为此上下文定义。

IBM JSSE 参考指南 说:

如果 KeyManager[] 参数为 null,则安装的安全性
将搜索提供商以获取最高优先级的实施
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());  

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

Using SSL from the Oracle JVM (JSSE)

See also "What TLS cipherspecs/ciphersuites are supported when connecting from Oracle Java (non-IBM JRE) to MQ queue manager?"

In MQ Client version 8.0.0.2 there is a patch is included to use the TLS with Oracle JVM, this works with lanes answer above

The get this to work you will need the latest MQ Client that contains
IV66840: WMQ V7 JAVA/JMS: ADD SUPPORT FOR SELECTED TLS CIPHERSPECS WHEN
RUNNING IN NON-IBM JAVA RUNTIME ENVIRONMENT
http://www-01.ibm.com/support/docview.wss?uid=swg1IV66840
(download)

Depending on your location you may also need to install
Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 8 (download)

To use this you have to configured by using the JVM argument:

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

Note that the default security implementation behaviour differs between Oracle and IBM JVMs :

The Oracle JSSE Reference guide says:

If the KeyManager[] parameter is null, then an empty KeyManager will
be defined for this context.

The IBM JSSE Reference guide says:

If the KeyManager[] paramater is null, the installed security
providers will be searched for the highest-priority implementation of
the KeyManagerFactory, from which an appropriate KeyManager will be
obtained.

Which means that you have to setup 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);

And then supply that to the MQ JMS client:

    JmsConnectionFactory cf = ...                                                                     

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

If using a application server this might be handled by your application server.

提笔落墨 2024-09-06 01:58:01

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

Be aware of which JRE you are using. We have had big trouble in using Sun JDK, because of a certain cryptation (TLS_RSA_WITH_AES_128_CBC_SHA) on the SSL channel to the IBM MQ. We used a X509 certeficate. In order to get it working we are using IBM JRE because it has much bigger support for certain cipher suites!

奈何桥上唱咆哮 2024-09-06 01:58:01

尝试此代码以及 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();
      }
   }
}

Try this code along with T.Robs explanations about the certificate:

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();
      }
   }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文