热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

问题将Java客户端(JMS)连接到IBMMQ-ProblemConnectingaJavaClient(JMS)toaIBMMQ

ImtryingtoconsumeanIBMMQ(version8.0.0.8)withSSLusingaJavaclientbuiltbasicallywith:

I'm trying to consume an IBM MQ (version 8.0.0.8) with SSL using a Java client built basically with:

我正在尝试使用基本构建的Java客户端使用SSL来使用IBM MQ(版本8.0.0.8):

  • Oracle JKD 8 and IBM JRE 7 (for testing purposes I have one client for each of them)
  • Oracle JKD 8和IBM JRE 7(出于测试目的,每个客户端都有一个客户端)

  • com.ibm.mq.allclient-9.1.0.0.jar
  • javax.jms-api-2.0.1.jarspring-jms-4.3.7.RELEASE.jar
  • spring-jms-4.3.7.RELEASE.jar

The MQ is a Request/Reply type.

MQ是请求/回复类型。

I have the correct certificate and all MQ properties set, but for some reason the connection “drops” and I get no errors on my client side and my requests never get any response and keeps running “forever”, never getting any response. The only clue that I have is an error message in the MQ log that says:

我有正确的证书和所有MQ属性设置,但由于某种原因连接“丢弃”,我的客户端没有错误,我的请求永远不会得到任何响应,并继续“永远”运行,永远不会得到任何响应。我所拥有的唯一线索是MQ日志中的错误消息:

Process(31600.16) User(QMQM) Jobname(JOB_NAME)
                    Host(HOST_NAME)
                    VRMF(8.0.0.8) QMgr(MANAGER_NAME)
                    AMQ9638: SSL communications error for channel 'CHANNEL_NAME'.   EXPLANATION:
    Cause . . . . . :   An unexpected SSL communications error occurred for a channel, as reported in the preceding messages. The
channel is 'CHANNEL_NAME';

The strange thing is that the SSL Handshake happens, my certificate is accepted by the MQ, but for some reason something happens after this. I’m trying using both Oracle JRE 8 and IBM JRE 7. Maybe is something on MQ side (IBM MQ v8.0.0.8) or some configuration that I’m missing on my side.

奇怪的是SSL握手发生了,我的证书被MQ接受,但由于某种原因,事后发生了一些事情。我正在尝试使用Oracle JRE 8和IBM JRE 7.也许是在MQ端(IBM MQ v8.0.0.8)或者我缺少的一些配置。

I have already installed the JCE Unlimited Policies, so the problem is not CipherSpec X CipherSuite.

我已经安装了JCE Unlimited Policies,所以问题不在于CipherSpec X CipherSuite。

I'm using -Djavax.net.debug=all and I can see that my certificate is being used correctly and I can't see any problems there...

我正在使用-Djavax.net.debug = all,我可以看到我的证书使用正确,我看不到任何问题......

My contact point on the MQ Team told me that for some reason my application is revoking the certificate (something related with CLR), but I have no idea why this would happen.

我在MQ团队的联系人告诉我,由于某种原因,我的应用程序正在撤销证书(与CLR相关的东西),但我不知道为什么会发生这种情况。

My Java code:

我的Java代码:

public Message callMQ() {

        Message message = null;

        try {

            MQConnectionFactory factory = mqQueueConnectionFactory();
            JMSContext cOntext= factory.createContext();

            Destination requestQueue = context.createQueue("queue:///REQUEST_QUEUE");
            Destination replyQueue = context.createQueue("queue:///REPLY_QUEUE");

            JmsTemplate jmsTemplate = new JmsTemplate(factory);

            FIXMLRootInbound inbound = new FIXMLRootInbound();
            String xml = XmlUtil.xmlObjectToString(inbound);

            message = jmsTemplate.sendAndReceive(requestQueue,
                    session -> {
                        Message req = session.createTextMessage(xml);
                        req.setJMSCorrelationID(UUID.randomUUID().toString());
                        req.setJMSDestination(requestQueue);
                        req.setJMSReplyTo(replyQueue);
                        return req;
                    });

        } catch (Throwable e) {
            e.printStackTrace();
        }

        return message;
    }

    private MQConnectionFactory mqQueueConnectionFactory() throws NoSuchAlgorithmException, KeyStoreException,
            IOException, CertificateException, UnrecoverableKeyException, KeyManagementException, JmsException {

        SSLSocketFactory sslSocketFactory = sslContext().getSocketFactory();

        MQEnvironment.sslSocketFactory = sslSocketFactory;
        MQEnvironment.sslCipherSuite = "TLS_RSA_WITH_AES_256_CBC_SHA";
        MQEnvironment.sslFipsRequired = false;

        MQConnectionFactory mqQueueCOnnectionFactory= new MQQueueConnectionFactory();
        mqQueueConnectionFactory.setHostName(host);
        try {
            mqQueueConnectionFactory.setTransportType(JMSC.MQJMS_TP_CLIENT_MQ_TCPIP);
            mqQueueConnectionFactory.setIntProperty(WMQConstants.WMQ_CONNECTION_MODE,
                    WMQConstants.WMQ_CM_CLIENT);
            mqQueueConnectionFactory.setQueueManager(queueManager);
            mqQueueConnectionFactory.setSSLCipherSuite("TLS_RSA_WITH_AES_256_CBC_SHA");
            mqQueueConnectionFactory.setCCSID(285);
            mqQueueConnectionFactory.setChannel(channel);
            mqQueueConnectionFactory.setPort(port);
            mqQueueConnectionFactory.setSSLSocketFactory(sslSocketFactory);
            mqQueueConnectionFactory.setSSLFipsRequired(false);
        } catch (Exception e) {
            log.error("Error creating MQQueueConnectionFactory.", e);
        }

        return mqQueueConnectionFactory;
    }

    private SSLContext sslContext() throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyManagementException {

        try (InputStream cert = new FileInputStream("C:\\myplace\\Dev\\Certificates\\MY_KEYSTORE.jks")) {

            final KeyStore caCertsKeyStore = KeyStore.getInstance("JKS");
            caCertsKeyStore.load(cert, "changeit".toCharArray());

            final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());

            CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX");
            PKIXRevocationChecker rc = (PKIXRevocationChecker)cpb.getRevocationChecker();
            rc.setOptions(EnumSet.of(
                    PKIXRevocationChecker.Option.PREFER_CRLS,
                    PKIXRevocationChecker.Option.ONLY_END_ENTITY,
                    PKIXRevocationChecker.Option.SOFT_FAIL,
                    PKIXRevocationChecker.Option.NO_FALLBACK));

            PKIXBuilderParameters pkixParams = new PKIXBuilderParameters(caCertsKeyStore, new X509CertSelector());
            pkixParams.addCertPathChecker(rc);

            kmf.init(caCertsKeyStore, "changeit".toCharArray());
            tmf.init( new CertPathTrustManagerParameters(pkixParams) );

            final SSLContext sslCOntext= SSLContext.getInstance("TLS");
            sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());

            return sslContext;

        } catch (Exception e) {
            throw new RuntimeException("Exception creating SSLContext", e);
        }
    }

1 个解决方案

#1


2  

Since you are using the 9.1.0.0 com.ibm.mq.allclient.jar you do not need all of the code you have related to the key store, for example:

由于您使用的是9.1.0.0 com.ibm.mq.allclient.jar,因此您不需要与密钥库相关的所有代码,例如:

SSLSocketFactory sslSocketFactory = sslContext().getSocketFactory();

//Note that MQEnvironment is used with IBM MQ Classes for Java not IBM MQ Classes for JMS
MQEnvironment.sslSocketFactory = sslSocketFactory;
MQEnvironment.sslCipherSuite = "TLS_RSA_WITH_AES_256_CBC_SHA";
MQEnvironment.sslFipsRequired = false;

mqQueueConnectionFactory.setSSLSocketFactory(sslSocketFactory);

private SSLContext sslContext() throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyManagementException {

    try (InputStream cert = new FileInputStream("C:\\myplace\\Dev\\Certificates\\MY_KEYSTORE.jks")) {

        final KeyStore caCertsKeyStore = KeyStore.getInstance("JKS");
        caCertsKeyStore.load(cert, "changeit".toCharArray());

        final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());

        CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX");
        PKIXRevocationChecker rc = (PKIXRevocationChecker)cpb.getRevocationChecker();
        rc.setOptions(EnumSet.of(
                PKIXRevocationChecker.Option.PREFER_CRLS,
                PKIXRevocationChecker.Option.ONLY_END_ENTITY,
                PKIXRevocationChecker.Option.SOFT_FAIL,
                PKIXRevocationChecker.Option.NO_FALLBACK));

        PKIXBuilderParameters pkixParams = new PKIXBuilderParameters(caCertsKeyStore, new X509CertSelector());
        pkixParams.addCertPathChecker(rc);

        kmf.init(caCertsKeyStore, "changeit".toCharArray());
        tmf.init( new CertPathTrustManagerParameters(pkixParams) );

        final SSLContext sslCOntext= SSLContext.getInstance("TLS");
        sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());

        return sslContext;

    } catch (Exception e) {
        throw new RuntimeException("Exception creating SSLContext", e);
    }
}

You can instead replace that with setting the following two system properties, this will work with both Oracle and IBM Java:

您可以通过设置以下两个系统属性来替换它,这将适用于Oracle和IBM Java:

System.setProperty("javax.net.ssl.keyStore", "C:\\myplace\\Dev\\Certificates\\MY_KEYSTORE.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "changeit");

The above settings have always worked for IBM Java, but with Oracle Java this did not work with older versions of MQ. It was fixed for Oracle java in the following versions of IBM MQ (Base 9.0 and 9.1 have the same fix):

上述设置一直适用于IBM Java,但使用Oracle Java时,这不适用于旧版本的MQ。在以下版本的IBM MQ中为Oracle java修复了它(Base 9.0和9.1具有相同的修复):

Version    Maintenance Level
v7.1       7.1.0.8
v7.5       7.5.0.7
v8.0       8.0.0.5

IBM Java and Oracle Java have different CipherSuite names, these are documented in the IBM MQ v9.1 Knowledge center page "TLS CipherSpecs and CipherSuites in IBM MQ classes for JMS.

IBM Java和Oracle Java具有不同的CipherSuite名称,这些名称记录在IBM MQ v9.1知识中心页面“用于JMS的IBM MQ类中的TLS CipherSpecs和CipherSuite”中。

You have specified TLS_RSA_WITH_AES_256_CBC_SHA in the posted code, this would be the SSLCIPH value on the MQ Queue manager SVRCONN channel, and would map to the following CipherSuites:

您已在发布的代码中指定了TLS_RSA_WITH_AES_256_CBC_SHA,这将是MQ队列管理器SVRCONN通道上的SSLCIPH值,并将映射到以下CipherSuite:

  • IBM Java: SSL_RSA_WITH_AES_256_CBC_SHA
  • IBM Java:SSL_RSA_WITH_AES_256_CBC_SHA

  • Oracle Java: TLS_RSA_WITH_AES_256_CBC_SHA
  • Oracle Java:TLS_RSA_WITH_AES_256_CBC_SHA

Related to the above, if you are using Oracle Java you need to set the following system property so that the MQ JMS classes will be able to use the right mapping of the Oracle CipherSuite name:

与上述相关,如果您使用的是Oracle Java,则需要设置以下系统属性,以便MQ JMS类能够使用Oracle CipherSuite名称的正确映射:

System.setProperty("com.ibm.mq.cfg.useIBMCipherMappings", "false");

The error you provided appears to be from the IBM i MQ Queue manager, but does not provide enough information to diagnose the problem.

您提供的错误似乎来自IBM i MQ队列管理器,但未提供足够的信息来诊断问题。

The error states the following:

该错误表明以下内容:

An unexpected SSL communications error occurred for a channel, as reported in the preceding messages.

Can you edit your question and provide the details from the "preceding messages".

您可以编辑您的问题并提供“之前的消息”中的详细信息。


You stated

for some reason my application is revoking the certificate (something related with CLR)

由于某种原因,我的申请正在撤销证书(与CLR相关的事情)

It could be that the MQ queue manager is attempting itself to connect to the OCSP server specified in the your client cert's AuthorityInfoAccess (AIA) certificate extension. If MQ can not reach this OCSP server with a default configuration the connection will be denied. If you are unable to update your network to allow connection to the OCSP server then you can disable this check but note that you will not know if a cert is revoked. To disable the checking the following can be added to the queue manager's qm.ini file SSL stanza:

可能是MQ队列管理器正在尝试连接到客户端证书的AuthorityInfoAccess(AIA)证书扩展中指定的OCSP服务器。如果MQ无法使用默认配置访问此OCSP服务器,则将拒绝连接。如果您无法更新网络以允许连接到OCSP服务器,则可以禁用此检查,但请注意您不知道是否撤销了证书。要禁用检查,可以将以下内容添加到队列管理器的qm.ini文件SSL节中:

SSL:
   OCSPAuthentication=Optional
   OCSPCheckExtensiOns=no

One last comment, the CipherSuite you listed in your example code TLS_RSA_WITH_AES_256_CBC_SHA is a TLS1.0 CipherSuite. Like SSL before it this and TLS1.1 are commonly deprecated across many industries. I looked for reference to post and a google of "tls 1.0 end of life" gives many references.

最后一条评论,您在示例代码TLS_RSA_WITH_AES_256_CBC_SHA中列出的CipherSuite是TLS1.0 CipherSuite。就像之前的SSL一样,TLS1.1在很多行业中都经常被弃用。我寻找帖子和谷歌“tls 1.0生命终结”的参考提供了许多参考。

Quoting one "TLS 1.0 end-of-life on June 30th, 2018" below:

下面引用一个“2018年6月30日的TLS 1.0寿命结束”:

The Deadline The PCI Council is responsible for determining when older protocols are phased out. They initially decided TLS 1.0 would reach end of life on 30 June 2016, later extending the date to 30 June 2018. The final deadline has past and all web servers, web browsers, web software and email applications have had to discontinue TLS 1.0 support, or fall foul of important security updates.

截止日期PCI委员会负责确定何时淘汰旧协议。他们最初决定TLS 1.0将于2016年6月30日终止,之后将日期延长至2018年6月30日。最后截止日期已过,所有网络服务器,网络浏览器,网络软件和电子邮件应用程序都不得不停止TLS 1.0支持,或者重要的安全更新。

I would suggest choosing one listed as TLS1.2 in the Knowledge center page I linked to above for example TLS_RSA_WITH_AES_256_CBC_SHA256.

我建议在我上面链接的知识中心页面中选择一个列为TLS1.2的版本,例如TLS_RSA_WITH_AES_256_CBC_SHA256。


推荐阅读
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • 标题: ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法
    本文介绍了解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法,包括检查location配置是否正确、pass_proxy是否需要加“/”等。同时,还介绍了修改nginx的error.log日志级别为debug,以便查看详细日志信息。 ... [详细]
  • springboot项目引入jquery浏览器报404错误的解决办法
    本文介绍了在springboot项目中引入jquery时,可能会出现浏览器报404错误的问题,并提供了解决办法。问题可能是由于将jquery.js文件复制粘贴到错误的目录导致的,解决办法是将文件复制粘贴到正确的目录下。如果问题仍然存在,可能是其他原因导致的。 ... [详细]
  • 基于Socket的多个客户端之间的聊天功能实现方法
    本文介绍了基于Socket的多个客户端之间实现聊天功能的方法,包括服务器端的实现和客户端的实现。服务器端通过每个用户的输出流向特定用户发送消息,而客户端通过输入流接收消息。同时,还介绍了相关的实体类和Socket的基本概念。 ... [详细]
  • 图像因存在错误而无法显示 ... [详细]
  • 本文介绍了使用Spark实现低配版高斯朴素贝叶斯模型的原因和原理。随着数据量的增大,单机上运行高斯朴素贝叶斯模型会变得很慢,因此考虑使用Spark来加速运行。然而,Spark的MLlib并没有实现高斯朴素贝叶斯模型,因此需要自己动手实现。文章还介绍了朴素贝叶斯的原理和公式,并对具有多个特征和类别的模型进行了讨论。最后,作者总结了实现低配版高斯朴素贝叶斯模型的步骤。 ... [详细]
  • Activiti7流程定义开发笔记
    本文介绍了Activiti7流程定义的开发笔记,包括流程定义的概念、使用activiti-explorer和activiti-eclipse-designer进行建模的方式,以及生成流程图的方法。还介绍了流程定义部署的概念和步骤,包括将bpmn和png文件添加部署到activiti数据库中的方法,以及使用ZIP包进行部署的方式。同时还提到了activiti.cfg.xml文件的作用。 ... [详细]
  • Servlet多用户登录时HttpSession会话信息覆盖问题的解决方案
    本文讨论了在Servlet多用户登录时可能出现的HttpSession会话信息覆盖问题,并提供了解决方案。通过分析JSESSIONID的作用机制和编码方式,我们可以得出每个HttpSession对象都是通过客户端发送的唯一JSESSIONID来识别的,因此无需担心会话信息被覆盖的问题。需要注意的是,本文讨论的是多个客户端级别上的多用户登录,而非同一个浏览器级别上的多用户登录。 ... [详细]
  • 开发笔记:spring boot项目打成war包部署到服务器的步骤与注意事项
    本文介绍了将spring boot项目打成war包并部署到服务器的步骤与注意事项。通过本文的学习,读者可以了解到如何将spring boot项目打包成war包,并成功地部署到服务器上。 ... [详细]
  • 微信官方授权及获取OpenId的方法,服务器通过SpringBoot实现
    主要步骤:前端获取到code(wx.login),传入服务器服务器通过参数AppID和AppSecret访问官方接口,获取到OpenId ... [详细]
author-avatar
asdasdasd
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有