fix: JT808修改-若NONE跳过鉴权
All checks were successful
aiot-platform CI/CD / build-and-deploy (push) Successful in 7m22s

This commit is contained in:
lzh
2025-12-26 18:40:00 +08:00
parent 1737566245
commit 69b0767fd7

View File

@@ -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 {
}
}
// ========== 鉴权码生成策略 ==========
// ========== 鉴权码生成和验证策略 ==========
/**
* 直接验证鉴权码(跳过注册步骤)
* <p>
* 当设备未注册或缓存过期时,根据设备的认证类型直接验证鉴权码
*
* @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;
}
}
/**
* 生成鉴权码