1. 程式人生 > >JAVA 編寫 IBM MQ Client SSL雙向通訊

JAVA 編寫 IBM MQ Client SSL雙向通訊

因為工作需要使用到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;
    }
}
這裡只貼出部分主要程式碼,有問題請私信