MQTT协议接入 - Java代码示例

小于 1 分钟

MQTT协议接入 - Java代码示例

package com.example;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;

/**
 * mqtt认证处理
 */
public class MqttAuthHandler {

  public static void main(String[] args) {
    Map<String, String> paramsDict = new HashMap<>();

    // MQTT连接参数
    var mqttUserName = "device&pk";
    var mqttClientId = "12345|securemode=3,signmethod=hmacsha1,timestamp=789|";
    var mqttPassword = "dc8f8498a1a115b58f6a3afd526bc62a1665bf48";

    // 设备密钥
    var deviceSecret = "secret";


    String[] userNameInfo = mqttUserName.split("&");
    if (userNameInfo.length <= 1) {
      return;
    }

    paramsDict.put("deviceId", userNameInfo[0]);
    paramsDict.put("productId", userNameInfo[1]);

    String[] clientIdInfo = mqttClientId.split("\\|");
    if (clientIdInfo[0].length() > 0) {
      paramsDict.put("clientId", clientIdInfo[0]);
    }

    if (clientIdInfo.length > 1) {
      String[] extendParams = clientIdInfo[1].split(",");
      for (String param : extendParams) {
        String[] paramInfo = param.split("=");
        if (paramInfo.length > 1) {
          paramsDict.putIfAbsent(paramInfo[0], paramInfo[1]);
        }
      }
    }

    String plainPasswd = paramsDict.containsKey("clientId") ? "clientId" + paramsDict.get("clientId") : "clientId";
    plainPasswd += "deviceId" + paramsDict.get("deviceId") + "productId" + paramsDict.get("productId") +
      (paramsDict.containsKey("timestamp") ? "timestamp" + paramsDict.get("timestamp") : "timestamp");

    Map<String, String> algorithmFormatDict = Map.of(
      "hmacmd5", "%032x",
      "hmacsha1", "%040x",
      "hmacsha256", "%064x"
    );

    String algorithm = paramsDict.getOrDefault("signmethod", "hmacmd5").toLowerCase();
    String format = algorithmFormatDict.getOrDefault(algorithm, "%032x");

    String signResult = null;
    try {
      signResult = hmac(plainPasswd, deviceSecret, algorithm, format);
    } catch (Exception ex) {
      ex.printStackTrace();
      return;
    }

    assert signResult.equalsIgnoreCase(mqttPassword);
  }

  /**
   * HMAC加密
   *
   * @param plainText 明文
   * @param key       密钥
   * @param algorithm 算法
   * @param format    格式
   * @return 密文
   */
  private static String hmac(String plainText, String key, String algorithm, String format) throws Exception {
    if (plainText == null || key == null) {
      return null;
    }

    byte[] hmacResult = null;

    Mac mac = Mac.getInstance(algorithm);
    SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), algorithm);
    mac.init(secretKeySpec);
    hmacResult = mac.doFinal(plainText.getBytes());
    return String.format(format, new BigInteger(1, hmacResult));
  }
}