問題描述
在 MQ Java 客戶端中使用 SSL 時出錯 (Error while using SSL in MQ java client)
我使用 IBM MQ V7.5 客戶端並運行 Java 1.7 編寫了一個帶有 SSL 配置的 Java 客戶端。為此,我參考 Websphere MQ Java 的 SSL 配置/ JMS 客戶端,但是在創建 TrustStore 步驟 8 中,我使用了自簽名證書。(因為我沒有 CA 的證書,我在哪裡獲得 CA 的證書?)
我的客戶端 Java 代碼是
import com.ibm.mq.*;
import com.ibm.mq.constants.MQConstants;
public class MQProducer {
private static final String qManager = "QM1";
private static final String qName = "localq";
private static final String truloc = "C:\\Program Files (x86)\\IBM\\WebSphere MQ\\Qmgrs\\QM1\\ssl\\trustStore.jks";
private static final String keyloc = "C:\\Program Files (x86)\\IBM\\WebSphere MQ\\Qmgrs\\QM1\\ssl\\keyStore.jks";
public static void main(String args[]) {
try {
MQEnvironment.hostname = "192.168.43.5";
MQEnvironment.channel = "myChannel";
MQEnvironment.port = 1414;
MQEnvironment.userID = "Taneesha";
System.setProperty("javax.net.ssl.trustStore", truloc);
System.setProperty("javax.net.ssl.keyStore", keyloc);
System.setProperty("javax.net.ssl.keyStorePassword", "123456");
MQEnvironment.sslCipherSuite = "SSL_RSA_WITH_NULL_MD5";
MQQueueManager qMgr = new MQQueueManager(qManager);
int openOptions = MQConstants.MQOO_OUTPUT;
MQQueue queue = qMgr.accessQueue(qName, openOptions);
MQMessage msg = new MQMessage();
String message = "Hello world";
msg.writeUTF(message);
MQPutMessageOptions pmo = new MQPutMessageOptions();
queue.put(msg, pmo);
queue.close();
qMgr.disconnect();
} catch (MQException ex) {
ex.printStackTrace();
System.out.println("A WebSphere MQ Error occurred : Completion Code " + ex.completionCode
+ " Reason Code " + ex.reasonCode);
} catch (java.io.IOException ex) {
System.out.println("An IOException occurred whilst writing to the message buffer: " + ex);
}
}
}
我收到以下錯誤
MQJE001: Completion Code '2', Reason '2397'.
Caused by: com.ibm.mq.jmqi.JmqiException: CC=2;RC=2397;
AMQ9204: Connection to host '192.168.43.5(1414)' rejected.
[1=com.ibm.mq.jmqi.JmqiException[CC=2;RC=2397;
AMQ9771: SSL handshake failed.
[1=javax.net.ssl.SSLHandshakeException[No appropriate protocol
(protocol is disabled or cipher suites are inappropriate)],
3=kasun‑PC/192.168.43.5:1414 (kasun‑PC),
4=SSLSocket.startHandshake,
5=default]],
3=192.168.43.5(1414),
5=RemoteTCPConnection.protocolConnect]
請有人幫忙嗎?
參考解法
方法 1:
What is the MQ qmgr and client version? What is the Java/JDK version? If you are using latest versions of Java 7 or any version of Java 8, the SSL Cipher you are using has been disabled/decommissioned. Use a TLS Cipher.
Edit
The list of ciphersuites supported by MQ 7.5 is on http://www‑01.ibm.com/support/knowledgecenter/SSFKSJ_7.5.0/com.ibm.mq.dev.doc/q031290_.htm?lang=en You can try any of the ciphersuite whose cipherspec starts with TLS. Make sure the svrconn channel on the qmgr also updated with the correct cipherspec.
If you are just trying out MQ on your local machine and want to get rid of this, enable SSL protocol on the jvm. http://www.oracle.com/technetwork/java/javase/7u75‑relnotes‑2389086.html Look for /lib/security/java.security and comment/remove jdk.tls.disabledAlgorithms (usually the last line).
As a permanent fix you should use TLS instead of SSL as they are a security risk.
方法 2:
First, please see my answer SSL connect to MQ using .net mq client SSLV3? where I provide an SSL implementation procedure that makes the process much easier.
In this case though the error message reveals the issue:
No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
As Umpathy notes in his answer, this is often due to selection of a ciphersuite in the QMgr that is no longer supported by default. Although it is possible to select the setting in the channel and the client, the QMgr will refuse to use it based on the settings of SSLFIPS
, SSLSUITEB
, environment variables, or the SSL stanza in the qm.ini
file. Please see CipherSpec values supported in IBM MQ for the latest on which ciphers are supported and how to enable the deprecated ones.
You also ask Because I don't have certificate of the CA, Where I Get certificate of the CA?
The choice to use self‑signed certs is not a matter of whether you can find the CA signer for a given cert. If either side of the connection uses a CA‑signed certificate, the other side must have the signer for that certificate in their trust store or kdb, even if its personal certificate is self‑signed.
If either side is using CA‑signed certificates there are a few ways to find the signers.
- Best way is to fetch the certificate for which you need a signer and dump the details. The
Issuer Distinguished Name
will tell you which signer was used. If the cert comes from a reputable CA, most likely it will also contain a URL pointing to the authoritative source for the signer certificate. - Second‑best way is to ask the party who administers the remote node to look in the kdb or jks and extract the signer certs used for its personal cert. This is only for trusted parties though because anyone from whom you accept a signer certificate is trusted the same as a real CA. However, for the case that the remote node is a QMgr administered by someone in your own organization you can generally trust them to provide the legitimate signer certs.
Finally... Note that if you are using self‑signed certs, the other side must add your public key to their kdb or jks in order for you to connect. At the moment the two sides cannot agree on a protocol but as soon as they do they will validate each others' certificates. At that point the debugging procedure I provided in the link above should prove extremely helpful.
(by Kirishanthy、Umapathy、T.Rob)