如何禁用HiveMQ MQTT客户端证书验证?解决PKIX路径构建失败
解决方案:禁用HiveMQ MQTT客户端的证书验证
问题背景
连接MQTT Broker(如HiveMQ)时,因未配置信任证书导致SSL握手失败,错误信息如下:
com.hivemq.client.mqtt.exceptions.ConnectionFailedException: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
解决步骤
要跳过证书验证,需自定义一个信任所有证书的SSLContext,并替换HiveMQ客户端的默认SSL配置:
- 实现信任所有证书的SSLContext
创建自定义SSLContext,通过自定义X509TrustManager绕过证书校验逻辑。 - 替换MQTT客户端的SSL配置
在协议配置方法中,使用自定义SSLContext替代默认的SSL配置。
修改后的完整代码
public @ResponseBody GenericResponse testMqttConnection( @RequestBody AdvancedMQTTSetting mqttSetting, HttpServletRequest request) { GenericResponse response = new GenericResponse(); /* * Initialize the client builder with common settings */ MqttClientBuilder clientBuilder = MqttClient.builder() .identifier(Utils.generateUUID()) .serverAddress( new InetSocketAddress(mqttSetting.getBrokerUrl(), mqttSetting.getPort())); try { if (mqttSetting.getMqttVersion().equals(PayloadMqttVersion.VERSION_5_0)) { /* * Configure MQTT 5 client */ Mqtt5ClientBuilder mqtt5ClientBuilder = clientBuilder.useMqttVersion5(); mqtt5ClientBuilder .simpleAuth() .username(mqttSetting.getUsername()) .password(mqttSetting.getPassword().getBytes(StandardCharsets.UTF_8)) .applySimpleAuth(); /* * Apply Protocol Specific Settings */ applyProtocolSpecificSettings(mqtt5ClientBuilder, mqttSetting); Mqtt5BlockingClient mqtt5Client = mqtt5ClientBuilder.buildBlocking(); Mqtt5ConnAck connAck = mqtt5Client.connect(); /* * Handle Connection Result */ handleConnectionResult( response, connAck.getReasonCode() == Mqtt5ConnAckReasonCode.SUCCESS, (MqttBlockingClient) mqtt5Client); } else { /* * Configure MQTT 3 client */ Mqtt3ClientBuilder mqtt3ClientBuilder = clientBuilder.useMqttVersion3(); mqtt3ClientBuilder .simpleAuth() .username(mqttSetting.getUsername()) .password(mqttSetting.getPassword().getBytes(StandardCharsets.UTF_8)) .applySimpleAuth(); /* * Apply Protocol Specific Settings */ applyProtocolSpecificSettings(mqtt3ClientBuilder, mqttSetting); Mqtt3BlockingClient mqtt3Client = mqtt3ClientBuilder.buildBlocking(); Mqtt3ConnAck connAck = mqtt3Client.connect(); /* * Handle Connection Result */ handleConnectionResult( response, connAck.getReturnCode() == Mqtt3ConnAckReturnCode.SUCCESS, (MqttBlockingClient) mqtt3Client); } } catch (Exception e) { LOGGER.error(e.getMessage(), e); response.setError(true); response.setErrorMessage(StringConstants.CONNECTION_UNSUCCESSFULL); } return response; } private void applyProtocolSpecificSettings( MqttClientBuilderBase<?> clientBuilder, AdvancedMQTTSetting mqttSetting) { if (PayloadProtocolType.WS.equals(mqttSetting.getProtocolType()) || PayloadProtocolType.WSS.equals(mqttSetting.getProtocolType())) { clientBuilder.webSocketConfig( MqttWebSocketConfig.builder() .serverPath(mqttSetting.getServerPath()) .subprotocol("mqtt") .build()); } if (PayloadProtocolType.MQTTS.equals(mqttSetting.getProtocolType()) || PayloadProtocolType.WSS.equals(mqttSetting.getProtocolType())) { // 使用自定义SSLContext替代默认配置 clientBuilder.sslConfig(MqttSslConfig.builder().sslContext(createTrustAllSslContext()).build()); } } private static SSLContext createTrustAllSslContext() { try { // 创建信任所有证书的TrustManager X509TrustManager trustAllManager = new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) {} @Override public void checkServerTrusted(X509Certificate[] chain, String authType) {} @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } }; SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, new TrustManager[]{trustAllManager}, new SecureRandom()); return sslContext; } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("Failed to create trust-all SSLContext", e); } }
注意事项
- 仅测试环境使用:此方式完全跳过证书验证,会导致通信失去SSL安全保障,生产环境必须配置合法的信任证书,禁止使用该方案。
- 生产环境连接自签名证书Broker时,正确做法是将Broker证书导入客户端信任库(如JKS文件),而非禁用验证。
内容的提问来源于stack exchange,提问作者P SAI KIREETI
相关产品推荐
相关产品推荐

