jndi - 无法通过JNDI与Websphere MQ SSL channel 连接

标签 jndi ibm-mq ssl channel

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

当前,在WMQ端,有一个名为TestMgr的队列管理器。在此队列管理器下,我创建了两个通道。一个是PLAIN.CHL,它未指定SSL密码规范,另一个是SSL.CHL,其将SSL密码规范配置为RC4_MD5_US,将SSL身份验证配置为Optional

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

对于通道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服务器创建的密钥存储中提取了证书,并将其导入到别名为ibmwebspheremqtestmgr的JRE的信任存储(证书)中。

您是正确的,出现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的值为null,因此当我将其放入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连接成功连接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。您提供的选项(use plain channel for initial context and ssl channel for connection factory)也适用。但是我仍然想知道如何通过ssl通道工作获得初始上下文。非常感谢您的耐心配合。您的更新将不胜感激。

谢谢

最佳答案

我从不非常喜欢com.ibm.mq.jms.context.WMQInitialContextFactory。它将托管对象存储在队列中。因此,为了查找connectionFactory(告诉JMS如何连接到QMgr),首先必须连接到QMgr进行JNDI调用。因此,在调试SSL连接之前,您需要知道基础JNDI提供程序是否正在运行。

如果要跳过基于MQ的JNDI提供程序,而仅使用文件系统,请参阅Bobby Woolf文章here的更新版本。如果要继续使用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没有带有replace选项的define),然后定义对象,然后显示该对象。实际上,您是否看到两个对象都已定义?您可以同时连接并交互式显示它们吗?您可以使用显示的内容更新您的问题吗?

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

一旦知道是引起问题的是应用程序还是JNDI提供程序(或切换到不需要MQ连接的另一个JNDI提供程序,例如文件系统初始上下文),便可以确定下一步。

article linked above具有使用文件系统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版本的行继续。

然后,如果有问题,请遵循在this SO answer中描述的调试方案。请注意,即使您的频道上有SSLCAUTH(OPTIONAL),该应用也将需要一个信任库。这是因为该应用程序必须始终验证QMgr的证书,即使该应用程序未提供自己的证书也是如此。就我而言,我使用的是SSLCAUTH(REQUIRED),因此我的应用程序需要密钥库和信任库。您的问题提到QMgr有一个密钥库,但没有说您对应用程序做了什么。

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



更新:
响应评论,JMSAdmin工具是WMQ软件包的一部分。但是,WMQ附带了用于文件系统上下文和LDAP上下文的jar。 WMQInitialContextFactory是可选的,并作为SupportPac ME01交付。当将WMQInitialContextFactory与JMSAdmin工具(或JMSAdmin GUI或WMQ Explorer)一起使用时,必须使用主机,端口和通道来配置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");


按照this Infocenter page,这应该告诉上下文工厂类使用什么密码套件。当然,他们还需要知道信任存储在哪里(如果通道设置了SSLCAUTH(RQUIRED),可能还要知道密钥存储),因此您仍然需要在环境中获取这些值。您可以使用命令行变量,也可以尝试使用代码将其加载到环境中。您将同时需要-Djavax.net.ssl.trustStore=key2.jks-Djavax.net.ssl.trustStorePassword=????????

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

关于jndi - 无法通过JNDI与Websphere MQ SSL channel 连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10250569/

相关文章:

java - Wildfly 添加 ManagedExecutorService

java - 带有 Windows AD 的 Tomcat 6 领域配置

java - Tomcat 连接池化多个数据源

ssl - java.net.SocketException:带有JMS/JNDI和MQ系列的管道损坏

vb6 - IBM MQSeries ActiveX 写入消息错误

javascript - ajax 图像加载破坏了完整的 SSL

java - GlassFish 5 上的 JNDI 查找失败

triggers - 触发器监视器作为 MQ 服务对象 - 如何获取状态

java - SSL 连接中的 IllegalStateException,执行 SAML 登录?

windows - 是否有 API 可以在 Windows 上预先检索受信任的根证书列表?