2

我的 JMS 客户端通过 JNDI 连接到 WMQ。使用的初始上下文工厂是com.ibm.mq.jms.context.WMQInitialContextFactory.

目前,在 WMQ 端,有一个名为TestMgr. 在这个队列管理器下,我创建了两个通道。一种是PLAIN.CHL没有指定 SSL Cipher Spec,另一种是SSL.CHL配置 SSL Cipher SpecRC4_MD5_US和 SSL Authentication with Optional

我使用 IBM Key Management 工具为队列管理器创建了一个密钥库。密钥 db 的路径是[wmq_home]\qmgrs\TestMgr\ssl\key.

对于 channel PLAIN.CHL,我定义了一个队列连接工厂,例如:

DEF QCF(PlainQCF) QMANAGER(TestMgr) CHANNEL(PLAIN.CHL) HOST(192.168.66.23) PORT(1414)   TRANSPORT(client)

在 SSL 通道下SSL.CHL,我定义了一个队列连接工厂,如:

DEF QCF(SSLQCF) QMANAGER(TestMgr) CHANNEL(SSL.CHL) HOST(192.168.66.23) PORT(1414) TRANSPORT(client) SSLCIPHERSUITE(SSL_RSA_WITH_RC4_128_MD5)

现在我只能使用PlainQCF. 但未能查找 SSL 队列连接工厂。我的代码如下所示:

 Hashtable environment = new Hashtable();
    environment.put(Context.INITIAL_CONTEXT_FACTORY, "com.ibm.mq.jms.context.WMQInitialContextFactory");
    environment.put(Context.PROVIDER_URL, "192.168.66.23:1414/SSL.CHL");
    Context ctx = new InitialContext( environment );
    QueueConnectionFactory qcf = (QueueConnectionFactory) ctx.lookup("SSLQCF");
    qcf.createConnection();
    ....

查找 SSL 工厂时是否缺少一些上下文属性?连接然后我发现代码在网上挂new InitialContext( environment )了很长时间,快5分钟了,我得到了CC=2;RC=2009;AMQ9208...错误。

任何建议将不胜感激。JNDI无法连接SSL通道是真的吗?


@T.Rob,非常感谢您的回复。但是我们仍然想使用WMQInitialContextFactory,所以恐怕我仍然需要为此找到解决方案。

我刚刚定义了一次连接工厂。SSL 队列连接工厂的显示信息如下:

InitCtx> DISPLAY QCF(SSLQCF)
ASYNCEXCEPTION(ALL)
CCSID(819)
CHANNEL(SSL.CHL)
CLIENTRECONNECTOPTIONS(ASDEF)
CLIENTRECONNECTTIMEOUT(1800)
COMPHDR(NONE )
COMPMSG(NONE )
CONNECTIONNAMELIST(192.168.66.23(1414))
CONNOPT(STANDARD)
FAILIFQUIESCE(YES)
HOSTNAME(192.168.66.23)
LOCALADDRESS()
MAPNAMESTYLE(STANDARD)
MSGBATCHSZ(10)
MSGRETENTION(YES)
POLLINGINT(5000)
PORT(1414)
PROVIDERVERSION(UNSPECIFIED)
QMANAGER(TestMgr)
RESCANINT(5000)
SENDCHECKCOUNT(0)
SHARECONVALLOWED(YES)
SSLCIPHERSUITE(SSL_RSA_WITH_RC4_128_MD5)
SSLFIPSREQUIRED(NO)
SSLRESETCOUNT(0)
SYNCPOINTALLGETS(NO)
TARGCLIENTMATCHING(YES)
TEMPMODEL(SYSTEM.DEFAULT.MODEL.QUEUE)
TEMPQPREFIX()
TRANSPORT(CLIENT)
USECONNPOOLING(YES)
VERSION(7)
WILDCARDFORMAT(TOPIC_ONLY)

JNDI Provider 应该没问题,因为我可以成功查找普通连接工厂。此外,对于我的客户端应用程序,我从为 MQ 服务器创建的密钥库中提取了证书,并将其导入到我的 JRE 的信任库(cacerts)中,别名为ibmwebspheremqtestmgr

你是对的,有 2009 错误有一些日志条目:

=================================================================

4/20/2012 20:24:27 - Process(13768.3) User(MUSR_MQADMIN) Program(amqzmur0.exe)
                      Host(xxxx_host of my MQ) Installation(mqenv)
                      VRMF(7.1.0.0) QMgr(TestMgr)                
AMQ6287: WebSphere MQ V7.1.0.0 (p000-L111019).
EXPLANATION:
WebSphere MQ system information: 
Host Info         :- Windows Server 2003, Build 3790: SP2 (MQ Windows 32-bit) 
Installation      :- C:\IBM\WebSphereMQ (mqenv) 
Version           :- 7.1.0.0 (p000-L111019)
ACTION:
None. 

-------------------------------------------------------------------------------
4/20/2012 20:24:27 - Process(7348.116) User(MUSR_MQADMIN) Program(amqrmppa.exe)
                      Host(xxxx_host of my MQ) Installation(mqenv)
                      VRMF(7.1.0.0) QMgr(TestMgr)
AMQ9639: Remote channel 'SSL.CHL' did not specify a CipherSpec.

EXPLANATION:
Remote channel 'SSL.CHL' did not specify a CipherSpec when the local channel
expected one to be specified. 

The remote host is 'xxx_host of my app (192.168.66.25)'. 
The channel did not start.

ACTION:
Change the remote channel 'SSL.CHL' on host 'xxx_host of my app (192.168.66.25)' to
specify a CipherSpec so that both ends of the channel have matching
CipherSpecs.

----- amqcccxa.c : 3817 -------------------------------------------------------
4/20/2012 20:24:27 - Process(7348.116) User(MUSR_MQADMIN) Program(amqrmppa.exe)
                      Host(my app host) Installation(mqenv)
                    VRMF(7.1.0.0) QMgr(TestMgr)                    
AMQ9999: Channel 'SSL.CHL' to host 'xxx_host of my app (192.168.66.25)' ended
abnormally.

====================================================================

我也对错误日志有些困惑。我的应用程序在与我的 MQ 不同的机器上运行。但是日志显示Change the remote channel 'SSL.CHL' on host 'xxx_host of my app (192.168.66.25)' to specify a CipherSpec so that both ends of the channel have matching CipherSpecs.如何更改我的应用程序主机上的通道密码规范?


MQEnvironment 的更新...

回复评论。

的值为MQEnvironment.sslCipherSuite空,因此当我将它放入 env 哈希表时它会抛出 NullPointerExcetpion。但是我尝试了另一个environment.put(MQC.SSL_CIPHER_SUITE_PROPERTY, "SSL_RSA_WITH_RC4_128_MD5"),但它仍然失败并2009出现错误。

对于JMSAdmin工具,我已将配置更改为使用WMQInitialContextFactory. 像(JMSAdmin.config)这样的配置:

INITIAL_CONTEXT_FACTORY=com.ibm.mq.jms.context.WMQInitialContextFactory
PROVIDER_URL=192.168.66.23:1414/SYSTEM.DEF.SVRCONN

其余配置保留为默认值。

请注意,这里我使用默认频道SYSTEM.DEF.SVRCONN,以便我可以登录到管理控制台。如果我将频道更改为 SSL one SSL.CHL,我也无法登录到管理控制台。这里发生的错误就像我的客户端应用程序中的错误一样。

TestMgr另一个澄清,在我的客户端中,我使用跟随代码可以通过 channel 成功连接 qmgr( ) SSL.CHL

   MQConnectionFactory factory = new MQConnectionFactory();
    factory.setTransportType(JMSC.MQJMS_TP_CLIENT_MQ_TCPIP);
    factory.setQueueManager("TestMgr");
    factory.setSSLCipherSuite("SSL_RSA_WITH_RC4_128_MD5");
    factory.setPort(1414);
    factory.setHostName("192.168.66.23");
    factory.setChannel("SSL.CHL");

    MQConnection connection = (MQConnection) factory.createConnection();

现在问题就像你说的那样,那是初始上下文无法通过 SSL 通道连接到 qmgr。您提供的 option( use plain channel for initial context and ssl channel for connection factory) 也有效。但我仍然想知道如何通过 ssl 通道工作获得初始上下文。非常感谢您的耐心。您的更新将不胜感激。

谢谢

4

1 回答 1

1

我从来没有真正喜欢com.ibm.mq.jms.context.WMQInitialContextFactory过。它将托管对象存储在队列中。因此,为了查找connectionFactory告诉 JMS 如何连接到 QMgr 的 ,首先需要连接到 QMgr以进行 JNDI 调用。因此,在调试 SSL 连接之前,您需要知道底层 JNDI 提供程序是否正常工作。

如果您想跳过基于 MQ 的 JNDI 提供程序而只使用文件系统,请在此处查看Bobby Woolf 文章的更新版本。如果您想继续com.ibm.mq.jms.context.WMQInitialContextFactory阅读,请继续阅读,但请准备好提供更多配置信息。

运行 JMSAdmin 工具时,是否在创建对象后显示它们?例如,这是我的JMSAdmin.bat脚本之一:

# Connection Factory for Client mode
# Delete the Connection Factory if it exists
DELETE  CF(JMSDEMOCF)

# Define the Connection Factory
DEFINE  CF(JMSDEMOCF) +
        SYNCPOINTALLGETS(YES) +
        SSLCIPHERSUITE(NULL_SHA) +
        TRAN(client) +
        HOST(127.0.0.1) CHAN(SSL.SVRCONN) PORT(1414) +
        QMGR( )

# Display the resulting definition
DISPLAY CF(JMSDEMOCF)

这将删除对象(因为 JMSAdmin 没有使用替换选项定义)然后定义对象,然后显示它。您实际上看到两个对象都定义了吗?您可以连接并交互显示它们吗?你能用显示的内容更新你的问题吗?

如果是这样,那么每个示例程序的 JNDI 提供程序配置是什么样的?2009 表明至少存在与正在建立的 QMgr 的连接,因此确定遭受断开连接的事物是您的应用程序还是 JNDI 提供程序非常重要。要诊断这需要您用于 JNDI 提供程序的配置信息,以及在工作和失败情况下是否相同。如果不是,它们有何不同?

一旦您知道是应用程序还是 JNDI 提供程序导致了问题(或切换到另一个不需要 MQ 连接的 JNDI 提供程序,例如文件系统初始上下文),那么就可以确定接下来的步骤。

上面链接的文章包含使用文件系统 JNDI 提供程序的代码示例和托管对象脚本。您可能会注意到我粘贴在上面的脚本使用相同的 QMgr 名称。那是因为我写了文章的那一部分。当我想使用这些相同的示例切换到 SSL 时,我只需将 更新connectionFactory为指向 SSL 通道,它就可以工作了。

以下是我修改过的示例中的其他位:

java -Djavax.net.debug=ssl  ^
     -Djavax.net.ssl.trustStore=key2.jks  ^
     -Djavax.net.ssl.keyStore=key2.jks ^
     -Djavax.net.ssl.keyStorePassword=????????  ^
     -Djavax.net.ssl.trustStorePassword=???????? ^
     -cp "%CLASSPATH%"  ^
      com.ibm.examples.JMSDemo -pub -topic JMSDEMOPubTopic %*

注意:这^是 Windows 版本的续行。

然后如果有问题,我会按照我在这个 SO answer中描述的调试场景进行操作。请注意,即使SSLCAUTH(OPTIONAL)您的频道上有该应用程序,该应用程序也需要信任库。这是因为应用程序必须始终验证 QMgr 的证书,即使应用程序没有提供自己的证书。就我而言,我正在使用SSLCAUTH(REQUIRED),所以我的应用程序需要一个密钥库和一个信任库。您的问题提到 QMgr 有一个密钥库,但没有说明您为应用程序做了什么。

最后,2009 通常会在 QMgr 错误日志中生成一个条目。如果您仍然遇到问题,请使用这些日志条目更新您的问题。


更新:
回应评论,JMSAdmin 工具是 WMQ 包的一部分。但是,WMQ 它带有用于文件系统上下文和 LDAP 上下文的 jar。这WMQInitialContextFactory是可选的,作为SupportPac ME01提供。与 JMSAdmin 工具(或 JMSAdmin GUI 或 WMQ Explorer)一起使用WMQInitialContextFactory时,需要使用主机、端口和通道配置 PROVIDER_URL。例如:

PROVIDER_URL: <Hostname>:<port>/<SVRCONN Channel Name>
192.168.66.23:1414/SSL.SVRCONN

因此,在再次查看您的帖子后,我意识到您确实提供了WMQInitialContextFactory. 我正在寻找一个 JMSADmin.config 文件,但您在环境哈希表中有它。这就是问题所在。您正在尝试将 SSL 通道用于连接工厂WMQInitialContextFactory 连接工厂。这就是导致查找失败的原因。第WMQInitialContextFactory一个与 QMgre 建立 Java 连接,以便在队列中查找被管理的对象,例如 QCF。为了做到这一点,它需要知道为协商握手而设置通道的密码套件。现在,记录密码套件的*唯一*位置在 QCF 定义中。

尝试添加以下行:

environment.put(MQEnvironment.sslCipherSuite, "SSL_RSA_WITH_RC4_128_MD5");

根据这个信息中心页面,这应该告诉上下文工厂类使用什么密码套件。当然,他们还需要知道信任库在哪里(如果通道已SSLCAUTH(RQUIRED)设置,可能还有密钥库),因此您仍然需要在环境中获取这些值。您可以使用命令行变量或尝试使用代码将它们加载到环境中。您将同时需要-Djavax.net.ssl.trustStore=key2.jks-Djavax.net.ssl.trustStorePassword=????????

另一种选择是继续为WMQInitialContextFactory应用程序使用明文通道和 SSL 通道。如果明文通道具有非特权用户 ID 的 MCAUSER,则可以将其限制为仅连接到 QMgr 并访问包含受管理对象的队列。有了这些限制,任何人都可以使用该通道读取管理对象,但不能读取应用程序队列或管理队列。

于 2012-04-20T20:17:43.923 回答