【问题标题】:How to connect to IBM MQ from a Camel route with SSL connection?如何使用 SSL 连接从 Camel 路由连接到 IBM MQ?
【发布时间】:2017-06-05 23:11:25
【问题描述】:

我可以从骆驼路由成功连接到 IBM MQ 并初始化连接工厂 bean,但现在我想使用 SSL 连接。

  1. 我在服务器端为队列管理器创建密钥库,并创建证书并将其添加到其中。
  2. 我在客户端创建了一个信任库并将证书添加到其中。
  3. 现在我希望 MQ 连接工厂在连接到服务器时引用信任库。

这是我尝试过的:

<bean id="MyConnectionFactory" class="com.ibm.mq.jms.MQQueueConnectionFactory">
        <property name="transportType" value="${queue.transportType}" />
        <property name="channel" value="${queue.channel}" />
        <property name="hostName" value="${queue.hostName}" />
        <property name="port" value="${queue.port}" />
        <property name="queueManager" value="${queue.manager}" />
        <property name="sSLCipherSuite" value="SSL_RSA_WITH_NULL_MD5" />
        <property name="sSLCertStores" value="file:C:/Servers/TrustStore/truststore.jks" />
    </bean>

但这不起作用。返回了以下异常:

JMSWMQ0018: Failed to connect to queue manager 'QM_TEST_SSL' 
       with connection mode 'Client' and host name '10.3.13.161(1415)'.; 
       nested exception is com.ibm.mq.MQException: JMSCMQ0001: 
       WebSphere MQ call failed with compcode '2' ('MQCC_FAILED')
       reason '2397' ('MQRC_JSSE_ERROR').

谁能帮助指导我如何做到这一点?

【问题讨论】:

  • 我建议查找有关那些 MQ 错误代码的 IBM MQ 文档。 IBM 必须在某个地方有他们的意思的文档
  • 您找到解决问题的方法了吗?如果是这样,请告诉我们如何让有相同问题的其他人受益。

标签: apache-camel ibm-mq


【解决方案1】:

从安全的角度来看,客户端应该只接收可能与许多问题相关的一般错误消息。找出您的客户被拒绝的确切原因的最佳位置是队列管理器日志。我建议在那里查看是否有任何错误可以帮助您进一步确定问题。 根据给出的信息,我可以想到 3 个问题:

  1. 队列管理器通道设置了 SSLCAUTH(REQUIRED) 属性,但是根据您在此处给出的描述,客户端似乎没有使用它自己的证书进行连接。 SSLCAUTH(REQUIRED) 将意味着队列管理器将仅接受客户端使用其信任的证书连接的特定通道上的连接。检查通道定义并设置SSLCAUTH(OPTIONAL)

  2. 根据您的 IBM MQ 版本,您使用的 CipherSpec (SSL_RSA_WITH_NULL_MD5) 被认为是弱的,默认情况下不会被接受。您可以重新启用这些已弃用的 CipherSpec,有关如何执行此操作的说明可以在 following Knowledge Center page

  3. 上找到
  4. 客户端未获取信任库“C:/Servers/TrustStore/truststore.jks”,因此客户端无法信任队列管理器的证书。仔细检查您提供的路径并删除您添加到路径中的“文件:”(除非您被明确指示包含它)。

【讨论】:

    【解决方案2】:

    您没有说明您使用的是哪个版本的 IBM MQ 或什么 JRE,如果它不是最新版本的 IBM MQ 并且正在与 Oracle JRE 一起使用,那么 APAR IT10837 可能会有所帮助。

    在 Tom Leend 发布的 IBM developerWorks 博客“MQ Java, TLS Ciphers, Non-IBM JREs & APARs IT06775, IV66840, IT09423, IT10837 -- HELP ME PLEASE!”的末尾有一篇很好的关于上述 APAR 的文章。他为没有此修复程序的 Java 客户端提供了一个解决方法。

    APAR IT10837

    我要提到最后一个 APAR,那就是 IT10837(针对 V7.1.0.8 和 V7.5.0.7 并在 V8.0.0.5 中提供)。此 APAR 影响在 Oracle JRE 中运行的应用程序,这些应用程序使用 TLS CipherSuites 连接到队列管理器,其中正在使用的服务器连接通道将 SSLCAUTH 属性设置为“REQUIRED”(默认值)。这意味着客户端应该将证书传递给队列管理器,以便连接的客户端可以通过 MQ 服务器的身份验证。

    当应用程序在 Oracle JRE 中运行时,SunJSSE 提供程序没有为 TLS 套接字连接创建默认的内部密钥管理器对象,这意味着客户端签名的个人证书在握手期间无法用于客户端身份验证。 IBM JSSE 提供者会根据通过 Java 系统属性传递的信息来执行此操作:

    • javax.net.ssl.keyStore

    • javax.net.ssl.keyStorePassword

    由于默认情况下未创建 KeyManager 对象,因此未将客户端证书传递给队列管理器 (GSKit) 进行身份验证。因此,来自应用程序的连接将失败。在这种情况下,队列管理器会将以下错误消息写入其错误日志文件:

    AMQ9637(通道缺少证书)

    此 APAR 的修复是让 JMS 的 MQ 类和 Java 的类根据上面提到的两个 Java 系统属性中的信息读取证书密钥库,并在以下情况下根据该信息创建一个 KeyManager com.ibm.mq.cfg.useIBMCipherMappings 在 JVM 中设置为 false 值。然后可以在创建 SSLContext 时使用它(随后用于创建 SSLSocketFactory 并最终创建一个安全套接字对象)。

    有一个本地解决方法是由应用程序本身创建的 TrustManagerFactory 和 KeyManagerFactory 工厂对象用于适当的证书存储并初始化 SSLContext 对象这些对象。从此 SSLContext 对象和 SSLSocketFactory 可以创建并传递给 JMS 的 MQ 类(通过在 JMS 连接工厂上设置)或 Java 的类(通过在 MQEnvironment 或传递给 MQQueueManager 构造函数的哈希表中设置) .例如:

    ---- 代码片段开始----

    KeyStore keyStore = KeyStore.getInstance("JKS");
    java.io.FileInputStream keyStoreInputStream = new java.io.FileInputStream("/home/tom/myKeyStore.jks");
    keyStore.load (keyStoreInputStream, password_char_array);
    
    KeyStore trustStore trustStore = KeyStore.getInstance ("JKS");
    java.io.FileInputStream trustStoreInputStream = new java.io.FileInputStream("/home/tom/myTrustStore.jks");
    trustStore.load (trustStoreInputStream, password_char_array);
    
    keyStoreInputStream.close();
    trustStoreInputStream.close();
    
    KeyManagerFactory keyManagerFactory = 
      KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    TrustManagerFactory trustManagerFactory = 
      TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    keyManagerFactory.init(keyStore,password);
    trustManagerFactory.init(trustStore);
    
    SSLContext sslContext = SSLContext.getInstance("TLSv1"); 
    sslContext.init(keyManagerFactory.getKeyManagers(), 
      trustManagerFactory.getTrustManagers(), 
      null);
    SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); 
    
    // classes for JMS
    myJmsConnectionFactory.setObjectProperty(
      WMQConstants.WMQ_SSL_SOCKET_FACTORY, sslSocketFactory);
    
    // classes for Java
    MQEnvironment.sslSocketFactory = sslSocketFactory;
    

    ---- 代码片段结束----

    【讨论】:

      猜你喜欢
      • 2018-11-09
      • 2023-04-05
      • 2023-03-05
      • 1970-01-01
      • 2016-01-21
      • 2022-08-19
      • 2011-03-04
      • 2011-02-09
      • 2020-01-12
      相关资源
      最近更新 更多