![](/img/trans.png)
[英]Java client using JMS for connecting to IBM MQ Channel of TCP/IP throwing error
[英]Problem Connecting a Java Client (JMS) to a IBM MQ
我正在嘗試使用使用以下基本構建的Java客戶端使用SSL的IBM MQ(版本8.0.0.8):
MQ是一種請求/答復類型。
我已經設置了正確的證書和所有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';
奇怪的是發生了SSL握手,我的證書被MQ接受了,但是由於某些原因在此之后發生了某些事情。 我正在嘗試同時使用Oracle JRE 8和IBM JRE7。可能是MQ方面的某些東西(IBM MQ v8.0.0.8)或我缺少的某些配置。
我已經安裝了JCE無限策略,所以問題不是CipherSpec X CipherSuite。
我正在使用-Djavax.net.debug = all,可以看到我的證書被正確使用,並且在那里看不到任何問題...
我在MQ團隊的聯系點告訴我,由於某種原因,我的應用程序吊銷了證書(與CLR有關的某件事),但是我不知道為什么會發生這種情況。
我的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);
}
}
由於您使用的是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);
}
}
您可以通過設置以下兩個系統屬性來代替它,這將對Oracle和IBM Java均適用:
System.setProperty("javax.net.ssl.keyStore", "C:\\myplace\\Dev\\Certificates\\MY_KEYSTORE.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "changeit");
以上設置始終適用於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和Oracle Java具有不同的CipherSuite名稱,這些名稱記錄在IBM MQ v9.1知識中心頁面“ IBM MQ JMS的TLS CipherSpecs和CipherSuite”中 。
您已在發布的代碼中指定了TLS_RSA_WITH_AES_256_CBC_SHA
,這將是MQ隊列管理器SVRCONN
通道上的SSLCIPH
值,並將映射到以下CipherSuites:
SSL_RSA_WITH_AES_256_CBC_SHA
TLS_RSA_WITH_AES_256_CBC_SHA
與上述相關,如果您使用的是Oracle Java,則需要設置以下系統屬性,以便MQ JMS類將能夠使用Oracle CipherSuite名稱的正確映射:
System.setProperty("com.ibm.mq.cfg.useIBMCipherMappings", "false");
您提供的錯誤似乎來自IBM i MQ隊列管理器,但是沒有提供足夠的信息來診斷問題。
該錯誤指出以下內容:
An unexpected SSL communications error occurred for a channel, as reported in the preceding messages.
您可以編輯問題並提供“先前消息”中的詳細信息嗎?
你說過
由於某種原因,我的申請正在吊銷證書(與CLR相關的問題)
MQ隊列管理器可能正在嘗試自行連接到客戶端證書的AuthorityInfoAccess(AIA)證書擴展名中指定的OCSP服務器。 如果MQ無法使用默認配置訪問此OCSP服務器,則連接將被拒絕。 如果您無法更新網絡以允許連接到OCSP服務器,則可以禁用此檢查,但是請注意,您將不知道證書是否被吊銷。 要禁用檢查,可以將以下內容添加到隊列管理器的qm.ini
文件SSL
節:
SSL:
OCSPAuthentication=Optional
OCSPCheckExtensions=no
最后一個注釋,您在示例代碼TLS_RSA_WITH_AES_256_CBC_SHA
列出的CipherSuite是TLS1.0 CipherSuite。 像之前的SSL一樣,許多行業通常不推薦使用此協議和TLS1.1。 我尋找發布的參考,“ tls 1.0生命終止 ”的google提供了很多參考。
在下面引用一個“ TLS 1.0壽命終止於2018年6月30日 ”:
期限 PCI委員會負責確定何時淘汰較舊的協議。 他們最初認為TLS 1.0將於2016年6月30日到期,后來將日期延長至2018年6月30日。最后期限已經過去,所有網絡服務器,網絡瀏覽器,網絡軟件和電子郵件應用程序都必須停止對TLS 1.0的支持,或違反重要的安全更新。
我建議選擇在上面鏈接到的知識中心頁面中列為TLS1.2的一個,例如TLS_RSA_WITH_AES_256_CBC_SHA256
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.