Centos 安装EMQX,使用自带的SSL双向认证,并用java验证

centos7安装EMQX

使用EMQ官网,选择系统环境和安装方式,进行下载安装
emqx broker
在这里插入图片描述使用指南中依赖包安装、特定版本安装、启动方式等命令。

EMQ X的SSL

/emqx/etc/certs里面存储自带的服务器证书和客户端证书
client-key-pkcs8.pem是另外生成,为了java连接用的,不在certs里面
注意:client-key-pkcs8.pem是另外生成,为了java连接用的,不在certs里面。

1.证书转换,将 client-key.pem 转换成 pkcs8 格式的证书:

// An highlighted block
openssl pkcs8 -topk8 -inform PEM -in client-key.pem -outform PEM -nocrypt -out client-key-pkcs8.pem

2.修改emqx.conf配置

/emqx/etc/emqx.conf里面主要是取消双向验证的注释即可

## A server only does x509-path validation in mode verify_peer,
## as it then sends a certificate request to the client (this
## message is not sent if the verify option is verify_none).
## You can then also want to specify option fail_if_no_peer_cert.
## More information at: http://erlang.org/doc/man/ssl.html
##
## Value: verify_peer | verify_none
listener.ssl.external.verify = verify_peer

## Used together with {verify, verify_peer} by an SSL server. If set to true,
## the server fails if the client does not have a certificate to send, that is,
## sends an empty certificate.
##
## Value: true | false
listener.ssl.external.fail_if_no_peer_cert = true

3.emqtt重启

使用zip安装的解压文件,进入/emqx/bin/emqx start

4.mqtt.fx客户端测试

在这里插入图片描述
注意protocil选择TLSv1.2
CA File 选择cacert.pem
Client Certificate File 选择client-cert.pem
Client Key File 选择client-key.pem
测试连接成功。

5.java模拟SSL连接(一)

注意,java代码验证的key文件,因为是key的pem格式不识别,需要转换成 pkcs8 格式的证书。需要使用第二部生成的文件client-key-pkcs8.pem。
并且自带的证书无password,所以用“”即可。

// An highlighted block

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;

import org.apache.commons.codec.binary.Base64;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;

public class EmqSSL {
	public static void main(String[] args) {
		EmqSSL ss = new EmqSSL();
		ss.connect();
	}
	private static void connect() {
		String topic = "MQTT Examples";
		String content = "Message from MqttPublishSample";
		int qos = 2;
		String broker = "ssl://IP地址:8883";
		String clientId = "JavaSample";
		MemoryPersistence persistence = new MemoryPersistence();

		try {
			MqttClient sampleClient = new MqttClient(broker, clientId, persistence);
			MqttConnectOptions connOpts = new MqttConnectOptions();
			connOpts.setCleanSession(true);
			SSLSocketFactory factory = null;
			try {
				factory = getSSLSocktet("E:\\test\\emqx\\etc\\certs\\cacert.pem",
						"E:\\test\\emqx\\etc\\certs\\client-cert.pem",
						"E:\\test\\emqx\\etc\\certs\\client-key-pkcs8.pem", "");
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			connOpts.setSocketFactory(factory);
			System.out.println("Connecting to broker: " + broker);
			sampleClient.connect(connOpts);
			System.out.println("Connected");
			System.out.println("Publishing message: " + content);
			MqttMessage message = new MqttMessage(content.getBytes());
			message.setQos(qos);
			sampleClient.publish(topic, message);
			System.out.println("Message published");
			sampleClient.disconnect();
			System.out.println("Disconnected");
			System.exit(0);
		} catch (MqttException me) {
			System.out.println("reason " + me.getReasonCode());
			System.out.println("msg " + me.getMessage());
			System.out.println("loc " + me.getLocalizedMessage());
			System.out.println("cause " + me.getCause());
			System.out.println("excep " + me);
			me.printStackTrace();
		}

	}

	private static SSLSocketFactory getSSLSocktet(String caPath, String crtPath, String keyPath, String password)
			throws Exception {
		// CA certificate is used to authenticate server
		CertificateFactory cAf = CertificateFactory.getInstance("X.509");
		FileInputStream caIn = new FileInputStream(caPath);
		X509Certificate ca = (X509Certificate) cAf.generateCertificate(caIn);
		KeyStore caKs = KeyStore.getInstance("JKS");
		caKs.load(null, null);
		caKs.setCertificateEntry("ca-certificate", ca);
		TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
		tmf.init(caKs);

		CertificateFactory cf = CertificateFactory.getInstance("X.509");
		FileInputStream crtIn = new FileInputStream(crtPath);
		X509Certificate caCert = (X509Certificate) cf.generateCertificate(crtIn);

		crtIn.close();
		// client key and certificates are sent to server so it can authenticate
		// us
		KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
		ks.load(null, null);
		ks.setCertificateEntry("certificate", caCert);
		ks.setKeyEntry("private-key", getPrivateKey(keyPath), password.toCharArray(),
				new java.security.cert.Certificate[] { caCert });
		KeyManagerFactory kmf = KeyManagerFactory.getInstance("PKIX");
		kmf.init(ks, password.toCharArray());

		// finally, create SSL socket factory
		SSLContext context = SSLContext.getInstance("TLSv1.2");

		context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());

		return context.getSocketFactory();
	}

	public static PrivateKey getPrivateKey(String path) throws Exception {

		org.apache.commons.codec.binary.Base64 base64 = new Base64();
		byte[] buffer = base64.decode(getPem(path));

		PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);

	}

	private static String getPem(String path) throws Exception {
		FileInputStream fin = new FileInputStream(path);
		BufferedReader br = new BufferedReader(new InputStreamReader(fin));
		String readLine = null;
		StringBuilder sb = new StringBuilder();
		while ((readLine = br.readLine()) != null) {
			if (readLine.charAt(0) == '-') {
				continue;
			} else {
				sb.append(readLine);
				sb.append('\r');
			}
		}
		fin.close();
		return sb.toString();
	}
}

6.java验证方式(二)

其中的crt文件,也是pem格式的。

package testMqttSSL;


import javax.net.ssl.SSLSocketFactory;
 
import java.security.Security;
 
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMReader;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;

import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyPair;
import java.security.KeyStore;

import java.security.SecureRandom;
import java.security.cert.X509Certificate;

public class SslUtil {
	
	public static void main(String[] args) throws MqttException {
		String topic = "MQTT Examples";
		String content = "Message from MqttPublishSample";
		int qos = 2;
		String broker = "ssl://192.168.20.197:8883";
		String clientId = "JavaSample";
		MemoryPersistence persistence = new MemoryPersistence();
		MqttClient sampleClient = new MqttClient(broker, clientId, persistence);
		MqttConnectOptions  mqttConnectOptions = new MqttConnectOptions();
		mqttConnectOptions.setCleanSession(true);
		//如果匿名登录连接,这2行注释掉
		mqttConnectOptions.setUserName("easthouse");
		mqttConnectOptions.setPassword("liberty".toCharArray());
		
		//mqtt 建立连接时赋值 双向
		 
		try {
			//经测试用crt证书
			mqttConnectOptions.setSocketFactory(SslUtil.getSocketFactory("D:\\emqttd-windows10-v2.3.3\\emqttd\\etc\\certs\\ca.crt",
					"D:\\emqttd-windows10-v2.3.3\\emqttd\\etc\\certs\\client.crt",
					"D:\\emqttd-windows10-v2.3.3\\emqttd\\etc\\certs\\client.key", ""));
		
			//单向         	
			 
//			mqttConnectOptions.setSocketFactory(SslUtil.getSocketFactorySingle(rootCrtPath));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("Connecting to broker: " + broker);
		sampleClient.connect(mqttConnectOptions);
		System.out.println("Connected");
		System.out.println("Publishing message: " + content);
		MqttMessage message = new MqttMessage(content.getBytes());
		message.setQos(qos);
		sampleClient.publish(topic, message);

	}
	public static SSLSocketFactory getSocketFactory(final String caCrtFile, final String crtFile, 
			final String keyFile,
			final String password) throws Exception {
		Security.addProvider(new BouncyCastleProvider());

		// load CA certificate
		PEMReader reader = new PEMReader(
				new InputStreamReader(new ByteArrayInputStream(Files.readAllBytes(Paths.get(caCrtFile)))));
		X509Certificate caCert = (X509Certificate) reader.readObject();
		reader.close();

		// load client certificate
		reader = new PEMReader(new InputStreamReader(new ByteArrayInputStream(Files.readAllBytes(Paths.get(crtFile)))));
		X509Certificate cert = (X509Certificate) reader.readObject();
		reader.close();

		// load client private key
		reader = new PEMReader(new InputStreamReader(new ByteArrayInputStream(Files.readAllBytes(Paths.get(keyFile)))));
		KeyPair key = (KeyPair) reader.readObject();
		reader.close();

		// CA certificate is used to authenticate server
		KeyStore caKs = KeyStore.getInstance(KeyStore.getDefaultType());
		caKs.load(null, null);
		caKs.setCertificateEntry("ca-certificate", caCert);
		TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
		tmf.init(caKs);

		// client key and certificates are sent to server so it can authenticate us
		KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
		ks.load(null, null);
		ks.setCertificateEntry("certificate", cert);
		ks.setKeyEntry("private-key", key.getPrivate(), password.toCharArray(),
				new java.security.cert.Certificate[] { cert });
		KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
		kmf.init(ks, password.toCharArray());

		// finally, create SSL socket factory
		SSLContext context = SSLContext.getInstance("TLSv1.2");
		context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

		return context.getSocketFactory();
	}

/*	public static SSLSocketFactory getSocketFactorySingle(final String caCrtFile) throws Exception {
		Security.addProvider(new BouncyCastleProvider());

		// load CA certificate
		PEMReader reader = new PEMReader(
				new InputStreamReader(new ByteArrayInputStream(Files.readAllBytes(Paths.get(caCrtFile)))));
		X509Certificate caCert = (X509Certificate) reader.readObject();
		reader.close();

		// CA certificate is used to authenticate server
		// KeyStore caKs = KeyStore.getInstance(KeyStore.getDefaultType());
		// caKs.load(null, null);
		// caKs.setCertificateEntry("ca-certificate", caCert);
		// TrustManagerFactory tmf =
		// TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
		// tmf.init(caKs);

		// client key and certificates are sent to server so it can authenticate us
		KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());// "JKS"
		ks.load(null, null);
		ks.setCertificateEntry("ca-certificate", caCert);
		TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());// "PKIX"
		tmf.init(ks);
		// finally, create SSL socket factory
		SSLContext context = SSLContext.getInstance("TLSv1.2");
		context.init(null, tmf.getTrustManagers(), new SecureRandom());

		// ----------------------------------------------------------------
		// CertificateFactory cAf = CertificateFactory.getInstance("X.509");
		// FileInputStream caIn = new FileInputStream(caPath);
		// X509Certificate ca = (X509Certificate) cAf.generateCertificate(caIn);
		// KeyStore caKs = KeyStore.getInstance("JKS");
		// caKs.load(null, null);
		// caKs.setCertificateEntry("ca-certificate", ca);
		// TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
		// tmf.init(caKs);
		//
		//
		// SSLContext context = SSLContext.getInstance("TLSv1");
		// context.init(null, tmf.getTrustManagers(), new SecureRandom());
		//
		// return context.getSocketFactory();

		return context.getSocketFactory();
	}*/
}

Connecting to broker: ssl://服务IP:8883
Connected
Publishing message: Message from MqttPublishSample
Message published
Disconnected

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值