物联网实战|spring-boot4 + hiveMQ|集成tls

📅 2026/7/8 2:08:48
物联网实战|spring-boot4 + hiveMQ|集成tls
物联网实战|spring-boot4 hiveMQ|集成tls源码如下(mqtt-simulator-hivemq-01)SAN是什么问题点ca证书生成window系统安装openssl将下面命名文件server.cnf,生成ca证书(包含subjectAltName-san)生成CA私钥(进入openssl目录bin下)生成CA证书生成结果ca证书转换jks借助keytools(进入jdk目录bin下)将server.crt拷贝过来spring-boot4 hiveMQ集成pom依赖代码如下结果如下如果ca缺失san证书基于spring-boot4 下面错误物联网实战|spring-boot4 hiveMQ|集成tls源码如下(mqtt-simulator-hivemq-01)https://gitee.com/kcnf-iot/mqtt-simulator/tree/master/mqtt-simulator-hivemq-01SAN是什么Subject DN主体名称旧标准里证书域名写在 CNCommon Name通用名字段只能填1 个域名 例CNshturl.cc/Y只能匹配这一个网址SAN主题备用名称是 X.509 证书标准扩展字段可以填写多个域名、IP、主机名支持 多个独立域名a.com、b.com 泛域名*.shturl. IP 地址192.168.1.1、IPv6 本地主机名、邮箱等问题点ca证书转换jksspring-boot4开启san强校验问题ca证书生成window系统安装opensslhttps://slproweb.com/products/Win32OpenSSL.html将下面命名文件server.cnf,生成ca证书(包含subjectAltName-san)[req] distinguished_name req_distinguished_name x509_extensions v3_req prompt no [req_distinguished_name] CN emqx.local [v3_req] keyUsage keyEncipherment, dataEncipherment, digitalSignature extendedKeyUsage serverAuth subjectAltName alt_names [alt_names] DNS.1 localhost IP.1 127.0.0.1 IP.2 192.168.0.20生成CA私钥(进入openssl目录bin下)openssl genrsa -out server.key 2048生成CA证书openssl req -x509 -new -nodes -key server.key -sha256 -days 3650 -out server.crt -config server.cnf生成结果ca证书转换jks借助keytools(进入jdk目录bin下)将server.crt拷贝过来keytool -importcert -alias server -file server.crt -keystore truststore.jks -storepass 123456 -nopromptspring-boot4 hiveMQ集成pom依赖dependencyManagement dependencies !-- Spring Boot Starter -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-dependencies/artifactId version4.0.6/version typepom/type scopeimport/scope /dependency /dependencies /dependencyManagement!-- HiveMQ MQTT5 客户端同时兼容 MQTT3.1.1 -- dependency groupIdcom.hivemq/groupId artifactIdhivemq-mqtt-client/artifactId version1.3.15/version /dependency代码如下package com.jysemel.iot; import com.hivemq.client.mqtt.MqttClientSslConfig; import com.hivemq.client.mqtt.mqtt5.Mqtt5AsyncClient; import com.hivemq.client.mqtt.mqtt5.Mqtt5Client; import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5SimpleAuth; import com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5Connect; import javax.net.ssl.TrustManagerFactory; import java.io.InputStream; import java.security.KeyStore; import java.util.UUID; public class HiveMQTLSClientExample { private static final String MQTT_HOST 192.168.0.20; private static final int MQTT_TLS_PORT 8085; private static final String MQTT_USER test; private static final String MQTT_PWD 123456; private static final int KEEP_ALIVE 30; public static void main(String[] args) { mqtt5AsyncClient(); } public static Mqtt5AsyncClient mqtt5AsyncClient() { // 1. 加载CA根证书构建SSL信任配置 MqttClientSslConfig sslConfig buildSslConfig(); // 2. 构建MQTT TLS客户端 String clientId server_ UUID.randomUUID().toString().substring(0, 16); Mqtt5AsyncClient client Mqtt5Client.builder() .identifier(clientId) .serverHost(MQTT_HOST) .serverPort(MQTT_TLS_PORT) .sslConfig(sslConfig) .buildAsync(); // 3. 构建连接报文 Mqtt5SimpleAuth simpleAuth Mqtt5SimpleAuth.builder() .username(MQTT_USER) .password(MQTT_PWD.getBytes()) .build(); Mqtt5Connect connectMsg Mqtt5Connect.builder() .cleanStart(true) .simpleAuth(simpleAuth) .keepAlive(KEEP_ALIVE) .build(); // 4. 发起异步连接 client.connect(connectMsg) .whenComplete((connAck, throwable) - { if (throwable ! null) { throwable.printStackTrace(); System.out.println(MQTT TLS连接失败 ); return; } System.out.println(MQTT TLS连接成功clientId ); }); return client; } private static MqttClientSslConfig buildSslConfig() { try { KeyStore trustStore KeyStore.getInstance(KeyStore.getDefaultType()); try (InputStream is HiveMQTLSClientExample.class.getResourceAsStream(/cert/emqx.jks)) { if (is null) { throw new RuntimeException(信任库文件未找到: /cert/emqx.jks); } String trustStorePassword 123456; trustStore.load(is, trustStorePassword.toCharArray()); } TrustManagerFactory tmf TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(trustStore); return MqttClientSslConfig.builder() .trustManagerFactory(tmf) // 关键自定义 HostnameVerifier总是验证通过仅测试用 .hostnameVerifier((hostname, session) - true) .build(); } catch (Exception e) { throw new RuntimeException(SSL 初始化失败, e); } } }结果如下如果ca缺失san证书基于spring-boot4 下面错误avax.net.ssl.SSLHandshakeException: No subject alternative names present com.hivemq.client.mqtt.exceptions.ConnectionFailedException: javax.net.ssl.SSLHandshakeException: No subject alternative names present Caused by: javax.net.ssl.SSLHandshakeException: No subject alternative names present at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:130) at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:383) at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:326) at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:321) at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.check