java实现通过pfx格式证书链接solace消息队列
一、证书准备
1.查看证书路径
2.pfx格式转pem格式证书
要拿到完整的证书先将pfx证书转成pem格式证书
将pfx证书转换为pem_win10pfx转pem在线-CSDN博客
记事本打开pem格式证书可以看到证书里面的结构是由PRIVATE KEY和完整的证书链组成
3.拆分证书(证书路径只有1级请忽略)
分别将证书CERTIFICATE上图框中的部分文本复制出,分别定义成3个txt格式文件,都改成crt格式证书
文件名字分别对应CN值,例如:
subject=C = CH, O = CloudProvider, CN = testcrt(在上图的每个证书头位置)
其中testcrt就是证书名字
这样我们有原始的pfx格式证书和上面步骤拿到的3(根据证书路径,不同的证书路径证书数量不同)个证书,一共4个证书
将4个证书复制到resources文件夹中
证书准备部分结束
二、代码实现
1.引入依赖
<dependency>
<groupId>com.solacesystems</groupId>
<artifactId>sol-jms</artifactId>
<version>10.10.0</version>
</dependency>
2.证书引入truststore
将上面3个crt格式正式引入truststore
private final String TRUST_STORE=System.getProperty("java.home")+"/lib/security/test.jks";
private void importCertificate() throws Exception {
//新建truststore
File cacertsfile = new File(TRUST_STORE);
if (!cacertsfile.exists()) {
KeyStore keystore = KeyStore.getInstance("PKCS12");
char[] password = trustStorePassWord.toCharArray();
keystore.load(null, password);
FileOutputStream out = new FileOutputStream(TRUST_STORE);
keystore.store(out, password);
out.close();
}
FileInputStream is = new FileInputStream(TRUST_STORE);
char[] password = trustStorePassWord.toCharArray();
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(is, password);
is.close();
//导入证书
ClassPathResource cssccpClassPathResource = new ClassPathResource("testcrtcrt");
ClassPathResource rocheca3ClassPathResource = new ClassPathResource("testcrt1.crt");
ClassPathResource rochecaClassPathResource = new ClassPathResource("testcrt2.crt");
Certificate cssccpCer = keyLoad(cssccpClassPathResource);
Certificate rocheca3Cer = keyLoad(rocheca3ClassPathResource);
Certificate rochecaCer = keyLoad(rochecaClassPathResource);
keystore.setCertificateEntry("testcrtcrt", cssccpCer);
keystore.setCertificateEntry("testcrt1", rocheca3Cer);
keystore.setCertificateEntry("testcrt2", rochecaCer);
FileOutputStream out = new FileOutputStream(TRUST_STORE);
keystore.store(out, password);
out.close();
}
public Certificate keyLoad(ClassPathResource classPathResource) throws IOException, CertificateException {
InputStream cssccpfis = classPathResource.getInputStream();
DataInputStream dis = new DataInputStream(cssccpfis);
byte[] bytes = new byte[dis.available()];
dis.readFully(bytes);
dis.close();
ByteArrayInputStream certstream = new ByteArrayInputStream(bytes);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Certificate certs = cf.generateCertificate(certstream);
return certs;
}
3.创建链接
@Bean
public void messageListenerContainer() throws Exception{
importCertificate();
ClassPathResource pfxtestClassPathResource = new ClassPathResource("pfxtest.pfx");
File file = pfxtestClassPathResource.getFile();
String pfxtestCertificateUrl = file.getAbsolutePath();
final JCSMPProperties properties = new JCSMPProperties();
properties.setProperty(JCSMPProperties.HOST, host);//host
properties.setProperty(JCSMPProperties.VPN_NAME, vpn);//vpn
properties.setProperty(JCSMPProperties.USERNAME, userName);//用户名
properties.setProperty(JCSMPProperties.PASSWORD, "");//username,password是必填属性,证书认证,密码可以为空
properties.setProperty(JCSMPProperties.SSL_VALIDATE_CERTIFICATE, true);
properties.setProperty(JCSMPProperties.SSL_VALIDATE_CERTIFICATE_DATE, true);
properties.setProperty(JCSMPProperties.AUTHENTICATION_SCHEME, SupportedProperty.AUTHENTICATION_SCHEME_CLIENT_CERTIFICATE);
properties.setProperty(JCSMPProperties.SSL_KEY_STORE, pfxtestCertificateUrl);
properties.setProperty(JCSMPProperties.SSL_KEY_STORE_PASSWORD, cerPassWord);//证书密码
properties.setProperty(JCSMPProperties.SSL_TRUST_STORE, TRUST_STORE);//truststore地址上文的jks文件地址
properties.setProperty(JCSMPProperties.SSL_TRUST_STORE_PASSWORD, trustStorePassWord);//truststore密码默认changeit
JCSMPChannelProperties channelProperties = (JCSMPChannelProperties) properties
.getProperty(JCSMPProperties.CLIENT_CHANNEL_PROPERTIES);
channelProperties.setConnectRetries(1);
channelProperties.setReconnectRetries(3);
channelProperties.setReconnectRetryWaitInMillis(3000);
channelProperties.setConnectRetriesPerHost(20);
session = JCSMPFactory.onlyInstance().createSession(properties);
session.connect();
System.out.println("连接成功!");
final Queue queue = JCSMPFactory.onlyInstance().createQueue(queueName);
session.provision(queue, null, JCSMPSession.FLAG_IGNORE_ALREADY_EXISTS);
final ConsumerFlowProperties flowProp = new ConsumerFlowProperties();
flowProp.setEndpoint(queue);
flowProp.setAckMode(JCSMPProperties.SUPPORTED_MESSAGE_ACK_CLIENT);
final FlowReceiver cons = session.createFlow(new SimpleMessageListener(), flowProp);
cons.start();
}
4.添加监听
private class SimpleMessageListener implements XMLMessageListener {
@Override
public void onReceive(BytesXMLMessage receivedMessage) {
numMessagesReceived.incrementAndGet();
if (receivedMessage instanceof com.solacesystems.jcsmp.TextMessage) {
lastReceivedMessage = (com.solacesystems.jcsmp.TextMessage) receivedMessage;
System.out.println("lastReceivedMessage:"+lastReceivedMessage);
System.out.println("---------message:messageId:"+lastReceivedMessage.getMessageId()+"------LocalDateTime"+ LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) +"-------text:"+lastReceivedMessage.getText());
AddInterfaceLog addInterfaceLog = new AddInterfaceLog();
addInterfaceLog.setCreatedBy("system");
addInterfaceLog.setCreatedTime(Timestamp.valueOf(LocalDateTime.now()));
try{
//具体业务逻辑
}catch (Exception e){
}
getManagerFeign.addInterfaceLog(addInterfaceLog);
}
}
@Override
public void onException(JCSMPException e) {
System.out.println("异常信息:"+e.getMessage());
}
}
备注:
java版本11
创建链接时运行到System.out.println("连接成功!");时连接成功
监听中记得最后要消费消息receivedMessage.ackMessage();
solace证书链接官方地址Secure Session | Solace API Tutorials