【代码评审】IoT:MQTT 连接参数

This commit is contained in:
YunaiV 2025-02-22 18:21:18 +08:00
parent 8043ce612f
commit fa40ae1dbd
6 changed files with 15 additions and 6 deletions

View File

@ -71,6 +71,7 @@ public interface IotDeviceUpstreamApi {
@PostMapping(PREFIX + "/add-topology") @PostMapping(PREFIX + "/add-topology")
CommonResult<Boolean> addDeviceTopology(@Valid @RequestBody IotDeviceTopologyAddReqDTO addReqDTO); CommonResult<Boolean> addDeviceTopology(@Valid @RequestBody IotDeviceTopologyAddReqDTO addReqDTO);
// TODO @芋艿考虑 http 认证
/** /**
* 认证 Emqx 连接 * 认证 Emqx 连接
* *

View File

@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.iot.api.device.dto.control.upstream;
import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotEmpty;
import lombok.Data; import lombok.Data;
// TODO @芋艿要不要继承 IotDeviceUpstreamAbstractReqDTO
/** /**
* IoT 认证 Emqx 连接 Request DTO * IoT 认证 Emqx 连接 Request DTO
* *

View File

@ -177,6 +177,7 @@ public class IotDeviceController {
return success(true); return success(true);
} }
// TODO @haohao是不是默认详情接口不返回 secret然后这个接口用于统一返回然后接口名可以更通用一点
@GetMapping("/mqtt-connection-params") @GetMapping("/mqtt-connection-params")
@Operation(summary = "获取 MQTT 连接参数") @Operation(summary = "获取 MQTT 连接参数")
@PreAuthorize("@ss.hasPermission('iot:device:mqtt-connection-params')") @PreAuthorize("@ss.hasPermission('iot:device:mqtt-connection-params')")

View File

@ -123,9 +123,7 @@ public class IotDeviceServiceImpl implements IotDeviceService {
private void initDevice(IotDeviceDO device, IotProductDO product) { private void initDevice(IotDeviceDO device, IotProductDO product) {
device.setProductId(product.getId()).setProductKey(product.getProductKey()) device.setProductId(product.getId()).setProductKey(product.getProductKey())
.setDeviceType(product.getDeviceType()); .setDeviceType(product.getDeviceType());
// 生成并设置必要的字段 // 生成密钥
// TODO @芋艿各种 mqtt 是不是可以简化
// clientIdusernamepassword 根据规则实时生成
device.setDeviceSecret(generateDeviceSecret()); device.setDeviceSecret(generateDeviceSecret());
// 设置设备状态为未激活 // 设置设备状态为未激活
device.setState(IotDeviceStateEnum.INACTIVE.getState()); device.setState(IotDeviceStateEnum.INACTIVE.getState());

View File

@ -280,6 +280,7 @@ public class IotDeviceUpstreamServiceImpl implements IotDeviceUpstreamService {
sendDeviceMessage(message, device); sendDeviceMessage(message, device);
} }
// TODO @haohao建议返回 boolean
@Override @Override
public Boolean authenticateEmqxConnection(IotDeviceEmqxAuthReqDTO authReqDTO) { public Boolean authenticateEmqxConnection(IotDeviceEmqxAuthReqDTO authReqDTO) {
log.info("[authenticateEmqxConnection][认证 Emqx 连接: {}]", authReqDTO); log.info("[authenticateEmqxConnection][认证 Emqx 连接: {}]", authReqDTO);
@ -303,6 +304,7 @@ public class IotDeviceUpstreamServiceImpl implements IotDeviceUpstreamService {
String deviceSecret = device.getDeviceSecret(); String deviceSecret = device.getDeviceSecret();
String clientId = authReqDTO.getClientId(); String clientId = authReqDTO.getClientId();
MqttSignResult sign = MqttSignUtils.calculate(productKey, deviceName, deviceSecret, clientId); MqttSignResult sign = MqttSignUtils.calculate(productKey, deviceName, deviceSecret, clientId);
// TODO @haohaonotEquals尽量不走取反逻辑哈
if (!StrUtil.equals(sign.getPassword(), authReqDTO.getPassword())) { if (!StrUtil.equals(sign.getPassword(), authReqDTO.getPassword())) {
log.error("[authenticateEmqxConnection][认证失败,密码不正确]"); log.error("[authenticateEmqxConnection][认证失败,密码不正确]");
return Boolean.FALSE; return Boolean.FALSE;

View File

@ -8,12 +8,15 @@ import java.nio.charset.StandardCharsets;
/** /**
* MQTT 签名工具类 * MQTT 签名工具类
* 提供静态方法来计算 MQTT 连接参数 *
* 提供静态方法来计算 MQTT 连接参数
*/ */
public class MqttSignUtils { public class MqttSignUtils {
private static final String SIGN_METHOD = "hmacsha256"; private static final String SIGN_METHOD = "hmacsha256";
// TODO @haohaocalculate 方法可以融合么
/** /**
* 计算 MQTT 连接参数 * 计算 MQTT 连接参数
* *
@ -25,11 +28,11 @@ public class MqttSignUtils {
public static MqttSignResult calculate(String productKey, String deviceName, String deviceSecret) { public static MqttSignResult calculate(String productKey, String deviceName, String deviceSecret) {
String clientId = productKey + "." + deviceName; String clientId = productKey + "." + deviceName;
String username = deviceName + "&" + productKey; String username = deviceName + "&" + productKey;
// 生成 password
// TODO @haohaosignContent signContentBuilder 风格保持统一的实现哈
String signContent = String.format("clientId%sdeviceName%sdeviceSecret%sproductKey%s", String signContent = String.format("clientId%sdeviceName%sdeviceSecret%sproductKey%s",
clientId, deviceName, deviceSecret, productKey); clientId, deviceName, deviceSecret, productKey);
String password = sign(signContent, deviceSecret); String password = sign(signContent, deviceSecret);
return new MqttSignResult(clientId, username, password); return new MqttSignResult(clientId, username, password);
} }
@ -54,6 +57,7 @@ public class MqttSignUtils {
return new MqttSignResult(clientId, username, password); return new MqttSignResult(clientId, username, password);
} }
// TODO @haohaohutool 貌似有工具类可以用哈
private static String sign(String content, String key) { private static String sign(String content, String key) {
try { try {
Mac mac = Mac.getInstance(SIGN_METHOD); Mac mac = Mac.getInstance(SIGN_METHOD);
@ -81,7 +85,9 @@ public class MqttSignUtils {
* MQTT 签名结果类 * MQTT 签名结果类
*/ */
@Getter @Getter
// TODO @haohao可以用 lombok
public static class MqttSignResult { public static class MqttSignResult {
private final String clientId; private final String clientId;
private final String username; private final String username;
private final String password; private final String password;