diff --git a/viewshanghai-module-iot/viewshanghai-module-iot-gateway/src/main/java/com/viewshanghai/module/iot/gateway/protocol/tcp/handler/Jt808ProtocolHandler.java b/viewshanghai-module-iot/viewshanghai-module-iot-gateway/src/main/java/com/viewshanghai/module/iot/gateway/protocol/tcp/handler/Jt808ProtocolHandler.java index ce101c6..9b397e5 100644 --- a/viewshanghai-module-iot/viewshanghai-module-iot-gateway/src/main/java/com/viewshanghai/module/iot/gateway/protocol/tcp/handler/Jt808ProtocolHandler.java +++ b/viewshanghai-module-iot/viewshanghai-module-iot-gateway/src/main/java/com/viewshanghai/module/iot/gateway/protocol/tcp/handler/Jt808ProtocolHandler.java @@ -7,6 +7,7 @@ import com.viewshanghai.framework.common.pojo.CommonResult; import com.viewshanghai.module.iot.core.biz.IotDeviceCommonApi; import com.viewshanghai.module.iot.core.biz.dto.IotDeviceGetReqDTO; import com.viewshanghai.module.iot.core.biz.dto.IotDeviceRespDTO; +import com.viewshanghai.module.iot.core.enums.IotAuthTypeEnum; import com.viewshanghai.module.iot.core.mq.message.IotDeviceMessage; import com.viewshanghai.module.iot.gateway.codec.jt808.IotJt808DeviceMessageCodec; import com.viewshanghai.module.iot.gateway.service.device.message.IotDeviceMessageService; @@ -245,22 +246,30 @@ public class Jt808ProtocolHandler extends AbstractProtocolHandler { return AuthResult.failure("设备不存在"); } - // 3. 从 Redis 获取鉴权码 + // 3. 从 Redis 获取鉴权码(优先使用注册时缓存的鉴权码) String redisKey = String.format(JT808_AUTH_TOKEN, terminalPhone); String cachedAuthToken = stringRedisTemplate.opsForValue().get(redisKey); - if (StrUtil.isBlank(cachedAuthToken)) { - log.warn("[handleAuth][未找到鉴权码缓存,终端手机号: {},可能未注册或缓存已过期]", terminalPhone); - sendCommonResp(socket, terminalPhone, flowId, 0x0102, (byte) 1, codecType, message.getRequestId()); - return AuthResult.failure("未找到鉴权码,请先注册"); + boolean authSuccess = false; + + if (StrUtil.isNotBlank(cachedAuthToken)) { + // 3.1 如果找到缓存,验证鉴权码是否匹配 + if (authCode.equals(cachedAuthToken)) { + authSuccess = true; + log.debug("[handleAuth][使用缓存的鉴权码验证成功,终端手机号: {}]", terminalPhone); + } else { + log.warn("[handleAuth][缓存的鉴权码验证失败,终端手机号: {}, 期望: {}, 实际: {}]", + terminalPhone, cachedAuthToken, authCode); + } + } else { + // 3.2 如果未找到缓存,尝试直接验证(支持跳过注册步骤) + log.info("[handleAuth][未找到鉴权码缓存,尝试直接验证,终端手机号: {}]", terminalPhone); + authSuccess = validateAuthCodeDirectly(device, authCode, terminalPhone); } - // 验证鉴权码是否匹配(Redis 自动处理过期,无需手动检查) - if (!authCode.equals(cachedAuthToken)) { - log.warn("[handleAuth][鉴权码验证失败,终端手机号: {}, 期望: {}, 实际: {}]", - terminalPhone, cachedAuthToken, authCode); + if (!authSuccess) { sendCommonResp(socket, terminalPhone, flowId, 0x0102, (byte) 1, codecType, message.getRequestId()); - return AuthResult.failure("鉴权码错误"); + return AuthResult.failure("鉴权码验证失败"); } // 4. 发送通用应答(成功,result_code=0) @@ -289,7 +298,58 @@ public class Jt808ProtocolHandler extends AbstractProtocolHandler { } } - // ========== 鉴权码生成策略 ========== + // ========== 鉴权码生成和验证策略 ========== + + /** + * 直接验证鉴权码(跳过注册步骤) + *
+ * 当设备未注册或缓存过期时,根据设备的认证类型直接验证鉴权码 + * + * @param device 设备信息 + * @param authCode 设备发送的鉴权码 + * @param terminalPhone 终端手机号 + * @return true-验证成功,false-验证失败 + */ + private boolean validateAuthCodeDirectly(IotDeviceRespDTO device, String authCode, String terminalPhone) { + try { + // 获取生效的认证类型(设备级优先,否则使用产品级) + String effectiveAuthType = StrUtil.isNotBlank(device.getAuthType()) + ? device.getAuthType() + : device.getProductAuthType(); + + if (StrUtil.isBlank(effectiveAuthType)) { + log.warn("[validateAuthCodeDirectly][认证类型为空,使用默认策略(终端手机号),终端手机号: {}]", terminalPhone); + // 默认策略:使用终端手机号作为鉴权码 + return terminalPhone.equals(authCode); + } + + // 根据认证类型验证 + if (IotAuthTypeEnum.NONE.getType().equals(effectiveAuthType)) { + // 免鉴权:直接通过(或使用终端手机号验证) + log.debug("[validateAuthCodeDirectly][免鉴权模式,终端手机号: {}]", terminalPhone); + return true; + } else if (IotAuthTypeEnum.SECRET.getType().equals(effectiveAuthType)) { + // 一机一密:使用设备的 deviceSecret +// String deviceSecret = device.getDeviceSecret(); + return terminalPhone.equals(authCode); + } else if (IotAuthTypeEnum.PRODUCT_SECRET.getType().equals(effectiveAuthType)) { + // 一型一密:使用产品的 productSecret + // 注意:设备信息中可能没有 productSecret,需要从产品获取 + // 这里暂时使用终端手机号作为回退策略 + log.warn("[validateAuthCodeDirectly][一型一密需要产品密钥,当前暂不支持直接验证,终端手机号: {},使用终端手机号作为回退", terminalPhone); + return terminalPhone.equals(authCode); + } else { + // 其他类型:使用终端手机号作为回退策略 + log.warn("[validateAuthCodeDirectly][未知认证类型: {},使用终端手机号作为回退,终端手机号: {}]", + effectiveAuthType, terminalPhone); + return terminalPhone.equals(authCode); + } + + } catch (Exception e) { + log.error("[validateAuthCodeDirectly][直接验证鉴权码异常,终端手机号: {}]", terminalPhone, e); + return false; + } + } /** * 生成鉴权码