JAVA 編寫 IBM MQ Client SSL雙向通訊
阿新 • • 發佈:2018-11-13
因為工作需要使用到IBM MQ ,但是大家都知道IBM MQ購買是很貴的,所以打算直接java編寫一個IBM MQ Client去和對方連線。因為自己沒有了解過這個,所以想先從IBM的官網下載一個IBM MQ去簡單連線測試一下,有興趣的朋友可以自己去查詢一下怎麼安裝下載,因為已經有很多帖子說明,在此不做介紹,簡單附上下載地址
https://developer.ibm.com/messaging/mq-downloads/
這裡主要說明一下怎麼使用java 編寫IBM MQ Client SSL雙向通訊
準備IBM_JAVA_SDK
需要的朋友可以去下面的地址下載,解壓即可用
https://download.csdn.net/download/qq_26182739/10424618
瞭解 MQSeries classes for Java 程式設計,附上中文pdf文件說明,簡單易懂
https://download.csdn.net/download/qq_26182739/10424746
前面準備做好後,開始上主要程式碼
//初始化訊息工廠,connect()方法在下方,只貼出部分方法主要程式碼 SSLContext ctx = connect(); System.setProperty("com.ibm.mq.cfg.useIBMCipherMappings", "true"); try { //MQ佇列管理器設定 mqConnectionFactory.setHostName("127.0.0.1"); mqConnectionFactory.setPort(1414); mqConnectionFactory.setQueueManager("QM.TEST.CLIENT.FPE001"); mqConnectionFactory.setChannel("test.01.TO.client.n");//通道名稱 mqConnectionFactory.setTransportType(WMQConstants.WMQ_CM_CLIENT); mqConnectionFactory.setCCSID(1381); //SSL相關配置 mqConnectionFactory.setSSLFipsRequired(true); mqConnectionFactory.setSSLSocketFactory(ctx.getSocketFactory()); //TLS_RSA_WITH_AES_256_CBC_SHA256對應通道的 ssl Cipher Spec 的值 mqConnectionFactory.setSSLCipherSuite(JmqiUtils.toCipherSuite("TLS_RSA_WITH_AES_256_CBC_SHA256")); //SSLPeerName請根據提供的證書資訊填寫,如果異常會提示正確的SSLPeerName mqConnectionFactory.setSSLPeerName("CN=test.mq.client.cn, OU=CLIENT, O=MQ TEST, C=CN"); //連線方式為client mqConnectionFactory.setMessageSelection(WMQConstants.WMQ_MSEL_CLIENT); mqConnectionFactory.setMQConnectionOptions(WMQConstants.WMQ_CM_CLIENT); logger.info("start create connection..."); //如果連線的時候,彈出檢查是否支援該使用者名稱、密碼,請在此處設定相應的使用者名稱,密碼 connection = mqConnectionFactory.createConnection("username","password"); logger.info("finish create connection..."); connection.start(); logger.info("connection start..."); //自動通知 //對於同步消費者,Receive方法呼叫返回,且沒有異常發生時,將自動對收到的訊息予以確認. //對於非同步訊息,當onMessage方法返回,且沒有異常發生時,即對收到的訊息自動確認 session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); } catch (JMSException e) { e.printStackTrace(); logger.error("fail connection:"+e.getMessage(),e); init = false; }
建立SSL 雙向連線方法的內容
怎麼建立金鑰以及金鑰庫,請自行搜尋,可以直接使用 keytool
keytool是jdk自帶的一款ssl管理工具,使用方法請參考下面這篇部落格,在此不做介紹
https://blog.csdn.net/fengwind1/article/details/52191520
/** * @Title:MqApplication * @Description:建立SSL雙向連線 * @return */ public static SSLContext connect() { SSLContext ctx = null; try { ctx = SSLContext.getInstance("TLSv1.2"); SSLContext.setDefault(ctx); KeyManagerFactory kmf = KeyManagerFactory.getInstance("IBMX509"); TrustManagerFactory tmf = TrustManagerFactory.getInstance("IBMX509"); KeyStore ks = KeyStore.getInstance("JKS"); KeyStore tks = KeyStore.getInstance("JKS"); String selfPasswd = "pass"; //客戶端私鑰檔案、根證書、由CA簽發的證書客戶端證書 ks.load(new FileInputStream(CommonUtils.appHome()+"keyStore"+System.getProperty("file.separator")+"keyStore.jks"), selfPasswd.toCharArray()); //服務端公鑰檔案 tks.load(new FileInputStream(CommonUtils.appHome()+"keyStore"+System.getProperty("file.separator")+"trustStore.jks"), selfPasswd.toCharArray()); kmf.init(ks, selfPasswd.toCharArray()); tmf.init(tks); TrustManager[] tm = tmf.getTrustManagers(); final X509TrustManager[] x509tm = Arrays.asList(tm).toArray(new X509TrustManager[tm.length]); X509TrustManager[] x509tmArray = new X509TrustManager[] { new X509TrustManager() { /* (non Javadoc) * @Title: getAcceptedIssuers * @Description: 返回受身份驗證同位體信任的認證中心的陣列 * @return * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers() */ @Override public X509Certificate[] getAcceptedIssuers() { return x509tm[0].getAcceptedIssuers(); } /* (non Javadoc) * @Title: checkClientTrusted * @Description: 給出同位體提供的部分或完整的證書鏈,構建到可任的根的證書路徑,並且返回是否可以確認和信任將其用於基於身份驗證型別的客戶端 SSL 身份驗證 * @param chain * @param authType * @throws CertificateException * @see javax.net.ssl.X509TrustManager#checkClientTrusted(java.security.cert.X509Certificate[], java.lang.String) */ @Override public void checkClientTrusted(X509Certificate[] chain, String authType){ for(int i=0;i<chain.length;i++) { logger.info("-------------------Check client cert"+i+"/"+authType+"---------------------"); } try { x509tm[0].checkClientTrusted(chain, authType); } catch (CertificateException e) { logger.error("Check client Cert Exception:"+e.getMessage(),e); } } /* (non Javadoc) * @Title: checkServerTrusted * @Description: 給出同位體提供的部分或完整的證書鏈,構建到可任的根的證書路徑,並且返回是否可以確認和信任將其用於基於身份驗證型別的伺服器 SSL 身份驗證 * @param chain 證書鏈 * @param authType 使用的金鑰交換演算法 RSAwith256 * @throws CertificateException 此證書鏈不受trustManager信任 * @see javax.net.ssl.X509TrustManager#checkServerTrusted(java.security.cert.X509Certificate[], java.lang.String) */ @Override public void checkServerTrusted(X509Certificate[] chain, String authType){ for(int i=0;i<chain.length;i++) { logger.info("-------------------Check server cert"+i+"/"+authType+"---------------------"); } try { x509tm[0].checkServerTrusted(chain, authType); logger.info("finish check server cert"); } catch (CertificateException e) { logger.error("Check server Cert Exception:"+e.getMessage(),e); e.printStackTrace(); } } } }; ctx.init(kmf.getKeyManagers(), x509tmArray, null); //返回支援的加密套件 // logger.info("Support CipherSuites:"+Arrays.asList(en.getSupportedCipherSuites())); //返回啟用的加密套件 // logger.info("Used CipherSuites:"+Arrays.asList(en.getEnabledCipherSuites())); } catch (Exception e) { e.printStackTrace(); logger.error("create ssl connection failer:"+e.getMessage(),e); } return ctx; }
傳送訊息
public class JmsProducer {
private Log logger = LogFactory.getLog(getClass());
Connection connection = null;
Destination destination = null;
MessageProducer producer = null;
Session session = null;
String line = null;
private static int status = 1;
public void JmsProducer() {
}
public void sendMsg() {
try {
session = MqApplication.session;
//佇列名稱從配置檔案讀取 建立佇列 client.TO.server.N
destination = session.createQueue(ConfigUtils.getConfig("mqManage/mq/outQueue"));//
//在jms會話中建立一個訊息的生產者
producer = session.createProducer(destination);
//開始連線
logger.info("start read file msg...");
//讀取檔案資訊
File file = new File(CommonUtils.appHome()+"keyStore"+System.getProperty("file.separator")+"message.xml");
BufferedReader in = new BufferedReader(new FileReader(file));
do {
line = in.readLine();
if (line!=null){
if(line.trim().length()==0){
break;
}
TextMessage message = session.createTextMessage(line);
//傳遞資訊
producer.send(message);
logger.info("send msg:\n"+message);
}
}
while (line != null);
recordSuccess();
} catch (Exception e) {
logger.error("send msg wrong"+e.getMessage(),e);
status = -1;
} finally {
if (producer != null) {
try {
producer.close();
}
catch (JMSException jmsex) {
logger.error("Producer could not be closed.");
}
}
if (session != null) {
try {
session.close();
}
catch (JMSException jmsex) {
logger.error("Session could not be closed.");
}
}
if (connection != null) {
try {
connection.close();
}
catch (JMSException jmsex) {
System.exit(status);
return;
}
}
}
}
private void recordSuccess() {
logger.info("SUCCESS");
status = 0;
return;
}
}
接收訊息
public class JmsConsumer {
private Log logger = LogFactory.getLog(getClass());
Connection connection = null;
Destination destination = null;
MessageConsumer consumer = null;
Session session = null;
String line = null;
private static int timeout = 15000;
private static int status = 1;
public void JmsConsumer() {
}
public void receiveMsg() {
try {
session = MqApplication.session;
//佇列名稱從配置檔案讀取 建立佇列 server.TO.client.N
destination = session.createQueue(ConfigUtils.getConfig("mqManage/mq/inQueue"));
//在jms會話中建立一個訊息的消費者
consumer = session.createConsumer(destination);
//開始連線
logger.info("start receive msg...");
//接收訊息
Message message;
do {
message = consumer.receive(timeout);
if (message != null) {
logger.info("receive msg:\n"+message);
}
}
while (message != null);
recordSuccess();
} catch (Exception e) {
logger.error("read msg wrong"+e.getMessage());
status = -1;
} finally {
if (consumer != null) {
try {
consumer.close();
}
catch (JMSException jmsex) {
logger.error("consumer could not be closed.");
}
}
if (session != null) {
try {
session.close();
}
catch (JMSException jmsex) {
logger.error("Session could not be closed.");
}
}
if (connection != null) {
try {
connection.close();
}
catch (JMSException jmsex) {
System.exit(status);
return;
}
}
}
}
private void recordSuccess() {
logger.info("SUCCESS");
status = 0;
return;
}
}
這裡只貼出部分主要程式碼,有問題請私信