为什么我无法通过 MQTT 连接到 Google Cloud IOT Core 中的设备?

Why can't I connect to device in Google Cloud IOT Core through MQTT?

我想在 Spring 启动时将我的后端连接到 Google Cloud Iot-Core 中我的硬件设置中的其中一个设备。我基本上复制了 this github repository 并调整了身份验证和连接选项。当我 运行 我的程序抛出这个异常时:

原因:org.springframework.beans.BeanInstantiationException:未能实例化[org.eclipse.paho.client。mqttv3.MqttClient]:工厂方法'connectToMqttClient'抛出异常;嵌套异常是不正确的用户名或密码 (4)

我用这个方法创建密码

private static String createJwtRsa(String projectId, String privateKeyFile)
        throws NoSuchAlgorithmException, IOException, InvalidKeySpecException {
    DateTime now = new DateTime();

    JwtBuilder jwtBuilder =
            Jwts.builder()
                    .setIssuedAt(now.toDate())
                    .setExpiration(now.plusMinutes(20).toDate())
                    .setAudience(projectId);

    byte[] keyBytes = Files.readAllBytes(Paths.get(privateKeyFile));
    PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
    KeyFactory kf = KeyFactory.getInstance("RSA");

    return jwtBuilder.signWith(SignatureAlgorithm.RS256, kf.generatePrivate(spec)).compact();
}

我遇到了 privateKeyFile 格式的问题。在 Iot-core 上,设备具有 RS256_X509

的 public 键

但是Spring Boot只允许RS256_PKCS8键格式,所以我不得不这样做:

  1. 我生成了 X509 格式的密钥 openssl req -x509 -nodes -newkey rsa:2048 -keyout rsa_private.pem -out rsa_cert.pem -subj "/CN=unused “ 它还生成了证书 rsa_cer.pem
  2. 我将密钥转换为 PKCS8 格式 openssl pkcs8 -topk8 -inform PEM -outform DER -in rsa_private.pem -out private_key.der -nocrypt
  3. 我在 Iot-core 中添加为 public 密钥的证书和 rsa_private.der 我在 createJwtRsa 方法中使用的证书

从那以后我得到了异常:不正确的用户名和密码。我能做些什么来修复它?

编辑:

我也尝试生成普通的 RSA256 密钥并将其转换为 PKCS8 格式,但我得到了同样的异常。与 ES256 键相同

我设法解决了这个问题! clientId 不正确

final String mqttClientId = String.format("projects/%s/locations/%s/registries/%s/devices/%s",
options.projectId, options.cloudRegion, options.registryId, options.gatewayId);

我的 gatewayId 是一个空字符串,因为我们没有在 Iot Core 上创建网关,我们直接连接到设备。 所以今天我将gatewayId设置为deviceId并且后端成功连接到设备。 所以现在这条线看起来像这样

final String mqttClientId = String.format("projects/%s/locations/%s/registries/%s/devices/%s",options.projectId, 
 options.cloudRegion, options.registryId, options.deviceId);