我正在用Java开发一个微服务,通过SSL连接到IBM Websphere MQ V8.0。然而,我在日志中看到了这个错误:
JMSCMQ0001:IBM MQ调用失败,编译代码为"2"("MQCC_failed"),原因为"2059"("MQ RC_Q_MGR_NOT_AVAILABLE")
MQ端的错误为CSQX673E
,原因是:
SSL或TLS通道的通道名称配置为使用证书标签:cert标签。但是,远程对等方没有发送必要的信息以允许本地通道使用正确的证书。远程主机已连接。
有人能告诉我如何使用Java传递这个参数吗。
据我所知,CERTLABL
不是证书的一部分。
请注意,以下信息在MQ v8.0.0、v9.0.0和v9.1.0知识中心中的记录相同。
IBM文档IBM MQ 8.0.0知识中心页面IBM MQ>安全>安全概述>IBM MQ安全机制>IBM MQ中的安全协议>SSL或TLS密钥存储库>数字证书标签,了解以下要求:
IBM MQ Version 8.0支持在相同的队列管理器,使用每通道证书标签属性。到队列管理器的入站通道(例如,服务器连接或接收器)依赖于使用TLS服务器名称检测通道名称指示(SNI),以便从队列管理器。
同一页也记录了这一点:
请注意,入站信道(包括接收器、集群接收器、,不合格的服务器和服务器连接通道)仅发送如果远程对等端的IBM MQ版本完全支持证书标签配置,并且通道使用TLS密码规范。
在所有其他情况下,队列管理器CERTLABL参数确定发送的证书。尤其是以下内容由队列的CERTLABL参数配置的证书管理器,不考虑特定频道的标签设置:
- 所有当前的Java和JMS客户端
- 8.0版之前的IBM MQ版本
IBM还在IBM MQ 8.0.0知识中心页面IBM MQ>参考>配置参考>通道属性>按字母顺序排列的通道属性>证书标签(CERTLABL):中记录了类似信息
入站通道(包括RCVR、CLUSRCVR、不合格SERVER和SVRCONN通道)将仅在远程对等机的IBM®MQ版本完全支持证书标签配置,并且通道使用TLS CipherSpec。如果是不是这样,队列管理器CERTLABL属性确定证书已发送。此限制是因为证书标签入站通道的选择机制取决于TLS协议不是在所有情况下都支持的扩展特别是Java™客户端、JMS客户端以及8.0版之前的所有IBM MQ版本不支持所需的协议扩展,并且只支持接收队列管理器CERTLABL配置的证书属性,而不考虑特定于频道的标签设置
正如您所说,Java 8确实支持SNI,但显然IBM尚未在IBM MQ Classes for Java或IBM MQ Classies for JMS中实现该功能。
我能想到的一个可能的解决方案是,您可以找出MQ调用哪个底层函数来创建TLS会话,并覆盖它,将SNI属性设置为MQ将在队列管理器上识别的值,代码如下:
SSLParameters params = sslSocket.getSSLParameters();
params.setServerNames(serverNames);
sslSocket.setSSLParameters(params);
IBM在Technote"IBM WebSphere MQ:MQ如何提供多个证书(CERTLABL)功能":中记录了在SNI中传递通道名称的格式
MQ使用的SNI地址基于被请求,后跟后缀".chl.mq.ibm.com".
MQ通道名称映射为有效的SNI名称,如下所示:
- 大写字母A-Z折叠为小写
- 数字0到9保持不变
- 包括小写字母a-z在内的所有其他字符都被转换为其2位十六进制ASCII字符代码,后跟连字符
- 小写字母a到z分别映射到"61-"到"7a-">
- 百分比(%)映射到"25-">
- 连字符(-)映射到"2d-">
- 点(.)映射到"2e-">
- 正斜杠(/)映射到"2f-">
- 下划线(_)映射到"5f-">
在EBCDIC平台上,通道名称在应用此映射。例如,通道名称"TO.QMGR1"映射到SNI地址"to2-qmgr1.chl.mq.ibm.com"。
相比之下,小写的通道名称"to.qmgr1"映射到SNI地址:"74-6f-2e-71-6d-67-72-1.chl.mq.ibm.com".