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