MQTT broker搭建并用SSL加密

系统为centos,基于emqx搭建broker,流程参考官方。

安装好后,用ssl加密。

进入/etc/emqx/certs,可以看到
在这里插入图片描述
分别为

  • cacert.pem CA 文件
  • cert.pem 服务端证书
  • key.pem 服务端key
  • client-cert.pem 客户端证书
  • client-key.pem 客户端key
    编辑emqx配置:vim /etc/emqx/emqx.conf,添加ssl配置:
listeners.ssl.default {# 端口bind = "0.0.0.0:8883"ssl_options {cacertfile = "/etc/emqx/certs/cacert.pem" #CA文件certfile = "/etc/emqx/certs/cert.pem"    #服务端证书keyfile = "/etc/emqx/certs/key.pem"   #服务端keyverify = verify_peer  # 双向认证fail_if_no_peer_cert = true}
}

再在客户端(如MQTTX)配置连接信息:在这里插入图片描述

Springboot订阅MQTTS

添加依赖

        <!--mqtt--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-integration</artifactId></dependency><dependency><groupId>org.springframework.integration</groupId><artifactId>spring-integration-stream</artifactId></dependency><dependency><groupId>org.springframework.integration</groupId><artifactId>spring-integration-mqtt</artifactId></dependency><!--ssl--><dependency><groupId>org.bouncycastle</groupId><artifactId>bcpkix-jdk15on</artifactId><version>1.64</version></dependency>

配置

spring:mqtt:provider:#MQTTS服务地址,端口号默认8883,如果有多个,用逗号隔开url: ssl://192.168.1.xx:8883#用户名username: xx#密码password: xxxx#客户端id(不能重复)client:id: provider-id#MQTT默认的消息推送主题,实际可在调用接口是指定default:topic: topicconsumer:url: ssl://192.168.1.xx:8883#用户名username: xx#密码password: xxxx#客户端id(不能重复)client:id: consumer-id#MQTT默认的消息推送主题,实际可在调用接口时指定default:topic: topic

Mqtt配置

@Configuration
public class MqttConsumerConfig {@Value("${spring.mqtt.consumer.username}")private String username;@Value("${spring.mqtt.consumer.password}")private String password;@Value("${spring.mqtt.consumer.url}")private String hostUrl;@Value("${spring.mqtt.consumer.client.id}")private String clientId;@Value("${spring.mqtt.consumer.default.topic}")private String defaultTopic;// 把证书文件放在在resource的ssl_certs目录下String caFilePath = "/ssl_certs/cacert.pem";String clientCrtFilePath = "/ssl_certs/client-cert.pem";String clientKeyFilePath = "/ssl_certs/client-key.pem";/*** 客户端对象*/private MqttClient client;/*** 在bean初始化后连接到服务器*/@PostConstructpublic void init() {connect();}/*** 客户端连接服务端*/@SneakyThrowspublic void connect() {
//        try {//创建MQTT客户端对象client = new MqttClient(hostUrl, clientId, new MemoryPersistence());//连接设置MqttConnectOptions options = new MqttConnectOptions();SSLSocketFactory socketFactory = getSocketFactory(caFilePath,clientCrtFilePath, clientKeyFilePath, "");options.setSocketFactory(socketFactory);/*允许所有host连接*/options.setSSLHostnameVerifier((s, sslSession) -> true);/*不配置可能出现报错java.security.cert.CertificateException: No subject alternative names present*/options.setHttpsHostnameVerificationEnabled(false);//是否清空session,设置为false表示服务器会保留客户端的连接记录,客户端重连之后能获取到服务器在客户端断开连接期间推送的消息//设置为true表示每次连接到服务端都是以新的身份options.setCleanSession(true);//设置连接用户名options.setUserName(username);//设置连接密码options.setPassword(password.toCharArray());//设置超时时间,单位为秒options.setConnectionTimeout(100);//设置心跳时间 单位为秒,表示服务器每隔1.5*20秒的时间向客户端发送心跳判断客户端是否在线options.setKeepAliveInterval(20);//设置遗嘱消息的话题,若客户端和服务器之间的连接意外断开,服务器将发布客户端的遗嘱信息options.setWill("willTopic", (clientId + "与服务器断开连接").getBytes(), 0, false);options.setAutomaticReconnect(true);//设置回调client.setCallback(new MqttCallbackImpl());client.connect(options);System.out.println(" 客户端连接成功 ");//订阅主题//消息等级,和主题数组一一对应,服务端将按照指定等级给订阅了主题的客户端推送消息int[] qos = {1, 1};//主题String[] topics = {"topicX#", "topicY#"};//订阅主题
//            client.subscribe("topicX",1);client.subscribe(topics);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }}/*** 断开连接*/public void disConnect() {try {client.disconnect();} catch (MqttException e) {e.printStackTrace();}}/*** 订阅主题*/public void subscribe(String topic, int qos) {try {client.subscribe(topic, qos);} catch (MqttException e) {e.printStackTrace();}}private static SSLSocketFactory getSocketFactory(final String caCrtFile,final String crtFile, final String keyFile, final String password)throws Exception {ClassPathResource caCrtFileRes = new ClassPathResource(caCrtFile);ClassPathResource crtFileRes = new ClassPathResource(crtFile);ClassPathResource keyFileRes = new ClassPathResource(keyFile);// add BouncyCastle providerSecurity.addProvider(new BouncyCastleProvider());// load CA certificateX509Certificate caCert = null;BufferedInputStream bis = new BufferedInputStream(caCrtFileRes.getStream());CertificateFactory cf = CertificateFactory.getInstance("X.509");while (bis.available() > 0) {caCert = (X509Certificate) cf.generateCertificate(bis);// System.out.println(caCert.toString());}// load client certificatebis = new BufferedInputStream(crtFileRes.getStream());X509Certificate cert = null;while (bis.available() > 0) {cert = (X509Certificate) cf.generateCertificate(bis);// System.out.println(caCert.toString());}// load client private keyPEMParser pemParser = new PEMParser(new InputStreamReader(keyFileRes.getStream()));Object object = pemParser.readObject();PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().build(password.toCharArray());JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");KeyPair key;if (object instanceof PEMEncryptedKeyPair) {System.out.println("Encrypted key - we will use provided password");key = converter.getKeyPair(((PEMEncryptedKeyPair) object).decryptKeyPair(decProv));} else {System.out.println("Unencrypted key - no password needed");key = converter.getKeyPair((PEMKeyPair) object);}pemParser.close();// CA certificate is used to authenticate serverKeyStore caKs = KeyStore.getInstance(KeyStore.getDefaultType());caKs.load(null, null);caKs.setCertificateEntry("ca-certificate", caCert);TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");tmf.init(caKs);// client key and certificates are sent to server so it can authenticate// usKeyStore 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 factorySSLContext context = SSLContext.getInstance("TLSv1.2");context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);return context.getSocketFactory();}}
@Slf4j
@Component
public class MqttCallbackImpl implements MqttCallback {@Overridepublic void connectionLost(Throwable throwable) {log.info("[MQTT] 连接断开");}@Overridepublic void messageArrived(String topic, MqttMessage message) throws Exception {String msg = new String(message.getPayload());log.info(String.format("接收消息主题 : %s", topic));log.info(String.format("接收消息Qos : %d", message.getQos()));log.info(String.format("接收消息内容 : %s", msg));log.info(String.format("接收消息retained : %b", message.isRetained()));}@Overridepublic void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {log.info("发送消息成功");}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/418169.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

云计算之大数据(下)

目录 一、Hologres 1.1 产品定义 1.2 产品架构 1.3 Hologres基本概念 1.4 最佳实践 - Hologres分区表 1.5 最佳实践 - 分区字段设置 1.6 最佳实践 - 设置字段类型 1.7 最佳实践 - 存储属性设置 1.8 最佳实践 - 分布键设置 1.9 最佳实践 - 聚簇键设置 1.10 最佳实践 -…

12. GIS地图制图工程师岗位职责、技术要求和常见面试题

本系列文章目录&#xff1a; 1. GIS开发工程师岗位职责、技术要求和常见面试题 2. GIS数据工程师岗位职责、技术要求和常见面试题 3. GIS后端工程师岗位职责、技术要求和常见面试题 4. GIS前端工程师岗位职责、技术要求和常见面试题 5. GIS工程师岗位职责、技术要求和常见面试…

多线程 | ThreadLocal源码分析

文章目录 1. ThreadLocal解决了什么问题数据隔离避免参数传递资源管理 2. ThreadLocal和Synchronized3. ThreadLocal核心核心特性常见方法使用场景注意事项 4. ThreadLocal如何实现线程隔离的&#xff1f;&#xff08;重点&#xff09;ThreadLocal 的自动清理与内存泄漏问题阿里…

浙大数据结构:02-线性结构3 Reversing Linked List

数据结构MOOC PTA习题 这道题也是相当费事&#xff0c;不过比上一个题好一些&#xff0c;这里我使用了C的STL库&#xff0c;使得代码量大幅减少。 题干机翻&#xff1a; 1、条件准备 这里我准备采用map来存地址和值&#xff0c;因为map的查找效率也是不错的 数组arr是存链…

GPU环境配置:1.CUDA、Anaconda、Pytorch

一、查看显卡适配CUDA型号 查看自己电脑的显卡版本&#xff1a; 在 Windows 设置中查看显卡型号&#xff1a;使用 Windows I 快捷键打开「设置」&#xff0c;依次点击「系统」-「屏幕」和「高级显示器设置」&#xff0c;在「显示器 1」旁边就可以看到显卡名称。 右键点菜单图标…

43. 1 ~ n 整数中 1 出现的次数【难】

comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/lcof/%E9%9D%A2%E8%AF%95%E9%A2%9843.%201%EF%BD%9En%E6%95%B4%E6%95%B0%E4%B8%AD1%E5%87%BA%E7%8E%B0%E7%9A%84%E6%AC%A1%E6%95%B0/README.md 面试题 43. 1 &#xff5e; n 整数中 1 …

前端 Vue3 项目开发—— ESLint prettier 配置代码风格

ESLint & prettier 介绍 如果你用的是 pnpm create vue 来创建项目&#xff0c;那么创建项目时就会让你选择是否添加 ESLint 和 prettier 我们在上一篇博客中详细介绍过 ESLint&#xff0c;可以说上一篇博客是这篇博客的先修知识&#xff0c;所以各位小伙伴们请先去看看我…

LiveQing视频点播流媒体RTMP推流服务功能-支持大疆等无人机RTMP推流支持OBS推流一步一步搭建RTMP视频流媒体服务示例

LiveQing支持大疆等无人机RTMP推流支持OBS推流一步一步搭建RTMP视频流媒体服务示例 1、流媒体服务搭建2、推流工具准备3、创建鉴权直播间4、获取推流地址5、配置OBS推流6、推流及播放7、获取播放地址7.1 页面查看视频源地址7.2 接口查询 8、相关问题8.1、大疆无人机推流花屏 9、…

【每日刷题】Day111

【每日刷题】Day111 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. LCR 047. 二叉树剪枝 - 力扣&#xff08;LeetCode&#xff09; 2. LCR 049. 求根节点到叶节点数字…

怎么在mathtype中打空格 MathType空格键不能用

MathType是一款数学公式编辑器&#xff0c;可以帮助用户创建复杂的数学公式和方程式。它提供了一个用户友好的界面&#xff0c;使得编辑和排版数学公式变得更加容易和高效。用户可以直接在其界面中输入公式&#xff0c;也可以将已有的公式从其他文档中复制粘贴过来进行编辑。在…

【STM32CubeMX】MPU6050移植DMP流程

原本是想要自己的模拟I2C库&#xff0c;来组合时选块&#xff0c;对接上DMP所需接口&#xff0c;可是一直卡在初始化&#xff0c;后面改成STM32F4的硬件I2C&#xff0c;也是很便捷的对接上接口了。此外在也参考了网上的移植资料与记录。本文也作为学习笔记&#xff0c;记录下过…

Java项目: 基于SpringBoot+mybatis+maven+mysql教师工作量管理系统(含源码+数据库+毕业论文)

一、项目简介 本项目是一套基于SpringBootmybatismavenmysql教师工作量管理系统 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美观…

软件测试 - 性能测试 (概念)(并发数、吞吐量、响应时间、TPS、QPS、基准测试、并发测试、负载测试、压力测试、稳定性测试)

一、性能测试 目标&#xff1a;能够对个人编写的项目进行接口的性能测试。 一般是功能测试完成之后&#xff0c;最后做性能测试。性能测试是一个很大的范围&#xff0c;在学习过程中很难直观感受到性能。 以购物软件为例&#xff1a; 1&#xff09;购物过程中⻚⾯突然⽆法打开…

JRebel and XRebel离线安装

近期&#xff0c;使用JRebel and XRebel&#xff0c;发现总是安装不上&#xff0c;可能是网络的原因吧。所以就使用离线方式进行安装。 JRebel 是一款用于 Java 开发的生产力工具。它的主要功能是加速开发周期&#xff0c;通过在不重启 JVM 的情况下即时加载代码变更。这样&…

在VB.net中,如何把20240906转化成日期格式

标题 vb.net中&#xff0c;如何把20240906转化成日期格式 正文 在 VB.NET 中&#xff0c;将一个数字字符串&#xff08;如 "20240906"&#xff09;转换为日期格式&#xff0c;你可以使用 DateTime.Parse 或 DateTime.TryParse 方法。这些方法可以将符合日期格式的字符…

Github 2024-09-07Rust开源项目日报Top10

根据Github Trendings的统计,今日(2024-09-07统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Rust项目10CUE项目1Python项目1Go项目1Polars: Rust中的DataFrame接口和OLAP查询引擎 创建周期:1354 天开发语言:Rust, Python协议类型:MIT …

【STM32开发】GPIO最全解析及应用实例

目录 【1】GPIO概述 GPIO的基本概念 GPIO的应用 【2】GPIO功能描述 1.IO功能框图 2.知识补充 3.功能详述 浮空输入 上拉输入 下拉输入 模拟输入 推挽输出 开漏输出 复用开漏输出和复用推挽输出 【3】GPIO常用寄存器 相关寄存器介绍 4个32位配置寄存器 2个32位数据寄存器 1个32位…

机器学习如何用于音频分析?

机器学习如何用于音频分析&#xff1f; 一、说明 近十年来&#xff0c;机器学习越来越受欢迎。事实上&#xff0c;它被用于医疗保健、农业和制造业等众多行业。随着技术和计算能力的进步&#xff0c;机器学习有很多潜在的应用正在被创造出来。由于数据以多种格式大量可用&…

JVM系列(十) -垃圾收集器介绍

一、摘要 在之前的几篇文章中,我们介绍了 JVM 内部布局、对象的创建过程、运行期的相关优化手段以及垃圾对象的回收算法等相关知识。 今天通过这篇文章,结合之前的知识,我们一起来了解一下 JVM 中的垃圾收集器。 二、垃圾收集器 如果说收集算法是内存回收的方法论,那么…

OrangePi AIpro 香橙派 昇腾 Ascend C 算子开发 与 调用 - 通过aclnn调用的方式调用AddCustom算子

OrangePi AIpro 香橙派 昇腾 Ascend C 算子开发 与 调用 通过aclnn调用的方式调用 - AddCustom算子 - 单算子API执行(aclnn) 多种算子调用方式 *开发时间使用场景调用方式运行硬件基于Kernel直调工程&#xff08;快速&#xff09;少单算子调用&#xff0c;快速验证算法逻辑IC…