SIGNATURE_FIX_SUMMARY.md 4.2 KB

License签名验证问题修复总结

问题描述

在项目中出现License签名验证失败的问题,根本原因是YudaoJacksonAutoConfiguration中配置的全局LocalDateTime序列化器与LicenseGenerator中的序列化配置不一致。

问题根本原因

  1. YudaoJacksonAutoConfiguration配置:使用TimestampLocalDateTimeSerializerLocalDateTime序列化为时间戳(Long类型)
  2. LicenseGenerator原始配置:使用标准Jackson配置,禁用WRITE_DATES_AS_TIMESTAMPS,将LocalDateTime序列化为ISO格式字符串
  3. 签名数据不一致:两种不同的时间格式导致签名数据字符串不同,进而导致签名验证失败

修复方案

1. 统一LicenseGenerator的序列化配置

修改LicenseGenerator构造函数,使其与项目的全局配置保持一致:

public LicenseGenerator() {
    this.objectMapper = new ObjectMapper();
    this.objectMapper.registerModule(new JavaTimeModule());
    
    // 使用与项目一致的LocalDateTime序列化配置,确保签名数据一致性
    SimpleModule simpleModule = new SimpleModule();
    simpleModule.addSerializer(LocalDateTime.class, TimestampLocalDateTimeSerializer.INSTANCE);
    simpleModule.addDeserializer(LocalDateTime.class, TimestampLocalDateTimeDeserializer.INSTANCE);
    this.objectMapper.registerModule(simpleModule);
    
    this.objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
}

2. 修改签名数据生成逻辑

更新appendField方法,确保时间字段在签名数据中也使用时间戳格式:

private void appendField(StringBuilder sb, String fieldName, Object value) {
    sb.append(fieldName).append("=");
    if (value != null) {
        // 对LocalDateTime字段使用时间戳格式,确保与JSON序列化一致
        if (value instanceof LocalDateTime) {
            LocalDateTime dateTime = (LocalDateTime) value;
            long timestamp = dateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
            sb.append(timestamp);
        } else {
            sb.append(value.toString());
        }
    }
    sb.append(";");
}

修复验证

测试结果

运行LicenseSignatureTest验证修复效果:

=== 序列化结果比较 ===
序列化结果是否一致: ✓ 是

=== 时间字段格式测试 ===
原始LocalDateTime: 2025-08-13T00:54:47.875317500
toString()格式: 2025-08-13T00:54:47.875317500
时间戳格式: 1755017687875
JSON序列化: 1755017687875

=== 签名数据生成测试 ===
生成的签名数据:
licenseId=TEST-LICENSE-001;customerName=测试客户;productName=测试产品;productVersion=1.0.0;createdTime=1755017687875;startTime=1755017687875;endTime=1757609687875;strategy=GRACEFUL_SHUTDOWN;gracePeriodDays=;warningDays=;maxUsers=100;

=== 测试完成 ===
结论: 修复成功,时间序列化格式已统一

关键验证点

  1. JSON序列化一致性:LicenseGenerator和项目配置的序列化结果完全一致
  2. 时间格式统一:所有时间字段都使用时间戳格式(1755017687875)
  3. 签名数据格式:签名数据中的时间字段也使用时间戳格式

修复的文件

  1. LicenseGenerator.java

    • 添加了与项目一致的LocalDateTime序列化配置
    • 修改了appendField方法以处理LocalDateTime字段
  2. 新增文件

    • LICENSE_SIGNATURE_ISSUE_SOLUTION.md:问题分析和解决方案文档
    • LicenseSignatureTest.java:签名一致性测试工具
    • SIGNATURE_FIX_SUMMARY.md:修复总结文档

后续建议

  1. 重新生成License文件:使用修复后的LicenseGenerator重新生成所有现有的License文件
  2. 集成测试:在实际环境中测试License的生成和验证流程
  3. 文档更新:更新License生成和使用的相关文档
  4. 监控机制:建立License验证的监控和告警机制

预防措施

  1. 建立License生成和验证的自动化测试
  2. 在CI/CD流程中加入License兼容性检查
  3. 统一项目中所有时间序列化的配置标准
  4. 定期检查Jackson配置变更对License系统的影响

修复状态: ✅ 已完成
验证状态: ✅ 已通过
修复时间: 2025-08-13