lipengcheng e80d39c3d7 first commit 1 ay önce
..
example e80d39c3d7 first commit 1 ay önce
src e80d39c3d7 first commit 1 ay önce
1 密钥与License生成流程.mermaid e80d39c3d7 first commit 1 ay önce
2 License验证流程.mermaid e80d39c3d7 first commit 1 ay önce
3 部署结构示意图 .mermaid e80d39c3d7 first commit 1 ay önce
LICENSE_SIGNATURE_ISSUE_SOLUTION.md e80d39c3d7 first commit 1 ay önce
QUICK_START.md e80d39c3d7 first commit 1 ay önce
README.md e80d39c3d7 first commit 1 ay önce
SIGNATURE_FIX_SUMMARY.md e80d39c3d7 first commit 1 ay önce
TestSignature.class e80d39c3d7 first commit 1 ay önce
TestSignature.java e80d39c3d7 first commit 1 ay önce
pom.xml e80d39c3d7 first commit 1 ay önce

README.md

BSKJ License Starter

基于国密SM2/SM3算法的Spring Boot License授权管理组件,提供完整的软件授权解决方案。

🚀 功能特性

🔐 授权策略

  • 通知模式 (NOTIFICATION_ONLY): 仅发送通知,不影响系统运行
  • 阻止重启 (PREVENT_RESTART): 许可证过期后阻止应用重启
  • 优雅关闭 (GRACEFUL_SHUTDOWN): 许可证过期后优雅关闭应用

🛡️ 安全特性

  • 基于国密SM2椭圆曲线数字签名算法
  • SM3哈希算法确保数据完整性
  • 防篡改的数字签名验证
  • 支持离线验证,无需联网
  • 时间戳序列化确保签名一致性

📊 监控与通知

  • 实时许可证状态监控
  • 到期前预警通知
  • 宽限期支持
  • 详细的审计日志

🔧 易于集成

  • Spring Boot Starter自动配置
  • 注解驱动的权限控制
  • 灵活的配置选项
  • 完整的事件监听机制
  • 全面的测试覆盖

快速开始

1. 添加依赖

在您的Spring Boot项目中添加依赖:

<dependency>
    <groupId>com.bskj.license</groupId>
    <artifactId>byjc-spring-boot-starter-license</artifactId>
    <version>1.0.0</version>
</dependency>

2. 配置文件

application.yml 中添加配置:

bskj:
  license:
    file-path: "license.json"
    public-key-path: "public.key"

3. 生成密钥对

# 生成RSA密钥对
java -cp bskj-license-starter-2025.08-SNAPSHOT.jar com.bskj.framework.license.generator.KeyGenerator private.key public.key

4. 生成License文件

方法一:引导式交互生成(推荐)

# 引导式生成license文件
java -cp "target/classes;target/dependency/*" com.bskj.framework.license.generator.LicenseGenerator

# 或者指定私钥和输出文件路径
java -cp "target/classes;target/dependency/*" com.bskj.framework.license.generator.LicenseGenerator private.key license.json

程序会引导您输入以下信息:

  • 客户名称
  • 产品名称和版本
  • 有效期(年)
  • 最大用户数
  • 警告天数和宽限期
  • 许可策略(仅通知/阻止重启/宽限期停止)
  • 模块权限配置

方法二:命令行参数生成

# 使用java -cp命令生成license文件
java -cp "target/classes;target/dependency/*" com.bskj.framework.license.generator.LicenseGenerator private.key license.json "客户名称"

5. 使用注解控制权限

@RestController
public class PatientController {
    
    @LicenseRequired(modules = {"patient_management"})
    @GetMapping("/patients")
    public List<Patient> getPatients() {
        // 需要patient_management模块授权
        return patientService.getAllPatients();
    }
    
    @LicenseRequired(checkUserLimit = true, strict = true)
    @PostMapping("/patients")
    public Patient createPatient(@RequestBody Patient patient) {
        // 检查用户数限制,严格模式
        return patientService.createPatient(patient);
    }
}

详细配置

License策略配置

bskj:
  license:
    # 授权策略
    default-strategy: "notification_only"  # notification_only | prevent_restart | graceful_shutdown
    
    # 检查配置
    check-on-startup: true
    enable-scheduled-check: true
    check-interval-seconds: 3600
    
    # 时间配置
    default-warning-days: 30      # 提前预警天数
    default-grace-period-days: 7  # 宽限期天数
    
    # 通知配置
    notification:
      log-enabled: true
      email-enabled: true
      email-recipients:
        - "admin@hospital.com"
        - "it@hospital.com"
      jmx-enabled: false

注解参数说明

@LicenseRequired(
    modules = {"billing", "reporting"},     // 需要的模块权限
    checkUserLimit = true,                   // 是否检查用户数限制
    allowExpired = false,                    // 是否允许过期时执行
    strict = false,                          // 是否为严格模式
    message = "需要计费模块授权"              // 自定义错误消息
)

License文件格式

License文件采用JSON格式,包含以下信息:

{
  "licenseId": "uuid",
  "customerName": "医院名称",
  "productName": "医疗管理系统",
  "productVersion": "1.0.0",
  "startTime": "2024-01-01T00:00:00",
  "endTime": "2025-01-01T00:00:00",
  "strategy": "notification_only",
  "gracePeriodDays": 7,
  "warningDays": 30,
  "maxUsers": 100,
  "modulePermissions": {
    "patient_management": true,
    "billing": true,
    "reporting": false
  },
  "extraProperties": {
    "hospitalCode": "H001",
    "region": "北京"
  },
  "createdTime": "2024-01-01T00:00:00",
  "signature": "base64-encoded-signature"
}

事件监听

您可以监听license相关事件来实现自定义逻辑:

@Component
public class LicenseEventListener {
    
    @EventListener
    public void handleStatusChange(LicenseMonitorService.LicenseStatusChangeEvent event) {
        // 处理状态变化
        logger.info("License status changed from {} to {}", 
                event.getPreviousStatus(), event.getCurrentStatus());
    }
    
    @EventListener
    public void handleNotification(LicenseMonitorService.LicenseNotificationEvent event) {
        // 处理通知事件
        sendEmailNotification(event.getTitle(), event.getMessage());
    }
    
    @EventListener
    public void handleShutdown(LicenseMonitorService.LicenseServiceShutdownEvent event) {
        // 处理服务停机事件
        logger.error("Service shutdown requested due to license: {}", event.getReason());
        // 执行优雅停机逻辑
    }
}

编程式使用

除了注解方式,您也可以直接使用LicenseService:

@Service
public class BusinessService {
    
    @Autowired
    private LicenseService licenseService;
    
    public void performBusinessOperation() {
        // 检查license状态
        if (!licenseService.isLicenseValid()) {
            throw new BusinessException("License无效");
        }
        
        // 检查模块权限
        if (!licenseService.isModulePermitted("advanced_analytics")) {
            throw new BusinessException("高级分析模块未授权");
        }
        
        // 检查用户数限制
        int currentUsers = getCurrentUserCount();
        if (!licenseService.isUserCountWithinLimit(currentUsers)) {
            throw new BusinessException("用户数超过限制");
        }
        
        // 执行业务逻辑
        doBusinessLogic();
    }
}

🧪 测试验证

项目提供了完整的测试套件,确保所有功能正常工作:

运行集成测试

# 运行完整的集成测试
mvn test -Dtest=LicenseIntegrationTest

# 运行所有测试
mvn test

测试覆盖范围

  • 密钥生成测试: 验证SM2密钥对生成和文件保存
  • License生成测试: 验证License文件创建和签名
  • 签名验证测试: 验证数字签名的正确性
  • 序列化一致性测试: 确保时间字段序列化格式统一
  • 时间字段测试: 验证LocalDateTime的处理逻辑

测试输出示例

[测试] 密钥生成测试
✓ 密钥生成测试通过
  - 私钥文件: /tmp/private.key
  - 公钥文件: /tmp/public.key

[测试] License生成测试
✓ License生成测试通过
  - License文件: /tmp/license.json
  - License ID: TEST-LICENSE-1692345678901
  - 客户名称: 测试客户

[测试] 签名验证测试
✓ 签名验证测试通过
  - 签名数据长度: 245
  - 签名数据: licenseId=TEST-LICENSE-1692345678901;customerName=测试客户;...

============================================================
所有测试通过!License系统工作正常
============================================================

🛠️ 工具类使用

命令行使用方式

1. 生成密钥对

# 编译项目
mvn compile

# 复制依赖
mvn dependency:copy-dependencies

# 生成密钥对
java -cp "target/classes;target/dependency/*" com.bskj.framework.license.generator.KeyGenerator private.key public.key

或者使用Maven exec插件:

mvn "exec:java@keygen" "-Dexec.args=private.key public.key"

2. 生成License

# 生成License文件(需要先生成密钥对)
java -cp "target/classes;target/dependency/*" com.bskj.framework.license.generator.LicenseGenerator private.key license.json 

Java代码使用方式

生成密钥对

KeyGenerator generator = new KeyGenerator();
generator.generateAndSaveKeyPair("private.key", "public.key");

生成License

LicenseGenerator generator = new LicenseGenerator();
generator.loadPrivateKey("private.key");

LicenseInfo license = LicenseGenerator.builder()
    .customerName("北京某医院")
    .productName("医疗管理系统")
    .productVersion("2.0.0")
    .startTime(LocalDateTime.now())
    .endTime(LocalDateTime.now().plusYears(1))
    .strategy(LicenseStrategy.PREVENT_RESTART)
    .maxUsers(200)
    .modulePermission("patient_management", true)
    .modulePermission("billing", true)
    .modulePermission("reporting", true)
    .extraProperty("hospitalLevel", "三甲")
    .build();

generator.generateLicense(license, "license.json");

🔧 架构设计

核心组件

  • KeyGenerator: SM2密钥对生成器
  • LicenseGenerator: License文件生成器,支持数字签名
  • CryptoUtil: 加密工具类,负责签名验证
  • LicenseIntegrationTest: 完整的集成测试套件

签名验证流程

  1. 签名生成: 使用私钥对License数据进行SM2签名
  2. 数据序列化: 统一使用时间戳格式序列化LocalDateTime
  3. 签名验证: 使用公钥验证License文件的完整性
  4. 一致性保证: 确保生成和验证使用相同的序列化格式

时间处理机制

  • JSON序列化: 使用TimestampLocalDateTimeSerializer将时间转为时间戳
  • 签名数据: 在appendField方法中特殊处理LocalDateTime字段
  • 一致性验证: 通过测试确保序列化格式统一

📋 最佳实践

🔒 安全建议

  1. 私钥保护

    • 私钥文件应存储在安全的位置
    • 设置适当的文件权限(如 600)
    • 考虑使用硬件安全模块(HSM)
    • 定期轮换密钥对
  2. License分发

    • 通过安全渠道分发license文件
    • 考虑加密传输
    • 记录license分发日志
  3. 监控告警

    • 设置license到期告警
    • 监控license验证失败事件
    • 建立license使用情况报告

🚀 部署建议

  1. 生产环境

    • 将公钥打包到应用中
    • License文件通过外部配置提供
    • 启用所有安全检查
    • 运行完整测试套件验证
  2. 测试环境

    • 使用独立的测试密钥对
    • 设置较短的license有效期
    • 启用详细日志
    • 定期运行集成测试

📊 监控建议

  1. 关键指标

    • License状态
    • 剩余有效期
    • 用户数量使用情况
    • 模块权限使用情况
    • 签名验证成功率
  2. 告警设置

    • 到期前30天、7天、1天告警
    • License验证失败告警
    • 用户数量超限告警
    • 签名验证异常告警

🎯 开发建议

  1. 代码同步

    • 保持KeyGenerator、LicenseGenerator和CryptoUtil的方法同步
    • 统一时间序列化处理逻辑
    • 定期运行集成测试验证一致性
  2. 测试驱动

    • 修改代码后必须运行测试
    • 新增功能需要添加对应测试
    • 保持测试覆盖率

👥 客户支持

  1. 常见问题处理

    • 提供license状态查询工具
    • 建立license问题处理流程
    • 准备常见问题解答文档
    • 提供测试工具验证License文件
  2. 技术支持

    • 提供license验证工具
    • 建立远程诊断能力
    • 准备应急处理预案
    • 提供集成测试指导

📊 性能监控

1. 关键指标监控

management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics
  metrics:
    tags:
      application: license-system

2. 自定义监控指标

@Component
public class LicenseMetrics {
    private final Counter verificationSuccessCounter;
    private final Counter verificationFailureCounter;
    private final Timer verificationTimer;
    
    // 监控License验证性能
}

🚨 应急处理

1. License紧急更新

# 1. 生成新的License文件
java -jar license-generator.jar --emergency

# 2. 验证新License
mvn test -Dtest=LicenseIntegrationTest

# 3. 部署新License
cp new-license.json /path/to/application/license.json

2. 回滚方案

# 1. 备份当前License
cp license.json license.json.backup

# 2. 恢复之前版本
cp license.json.old license.json

# 3. 重启应用验证
systemctl restart application

📞 技术支持

联系信息

问题报告模板

问题描述: [详细描述问题现象]
错误信息: [完整的错误日志]
环境信息: [操作系统、Java版本、应用版本]
复现步骤: [详细的复现步骤]
测试结果: [LicenseIntegrationTest运行结果]

📚 版本历史

v2.0.0 (当前版本)

  • ✅ 完整的集成测试套件
  • ✅ 时间戳序列化一致性保证
  • ✅ 增强的错误处理和日志
  • ✅ 详细的文档和故障排除指南
  • ✅ 性能监控和指标收集
  • ✅ SM2/SM3国密算法支持

v1.0.0

  • ✅ 基础License生成和验证功能
  • ✅ SM2密钥对生成
  • ✅ JSON格式License文件
  • ✅ 基本的权限控制

🤝 贡献指南

开发流程

  1. Fork项目

    git clone https://github.com/your-username/bskj-license-starter.git
    cd bskj-license-starter
    
  2. 创建功能分支

    git checkout -b feature/your-feature-name
    
  3. 开发和测试

    # 运行测试确保功能正常
    mvn test -Dtest=LicenseIntegrationTest
       
    # 运行所有测试
    mvn test
    
  4. 提交代码

    git add .
    git commit -m "feat: 添加新功能描述"
    git push origin feature/your-feature-name
    
  5. 创建Pull Request

    • 详细描述修改内容
    • 确保所有测试通过
    • 更新相关文档

代码规范

  1. Java代码规范

    • 遵循Google Java Style Guide
    • 使用有意义的变量和方法名
    • 添加必要的注释和JavaDoc
  2. 测试规范

    • 新功能必须包含对应测试
    • 保持测试覆盖率 > 80%
    • 测试方法命名清晰明确
  3. 提交信息规范

    type(scope): description
       
    [optional body]
       
    [optional footer]
    

类型说明:

  • feat: 新功能
  • fix: 修复bug
  • docs: 文档更新
  • test: 测试相关
  • refactor: 代码重构

问题反馈

  1. Bug报告

    • 使用Issue模板
    • 提供详细的复现步骤
    • 包含错误日志和环境信息
    • 运行LicenseIntegrationTest并提供结果
  2. 功能请求

    • 详细描述需求场景
    • 说明预期行为
    • 考虑向后兼容性

发布流程

  1. 版本规划

    • 主版本号:不兼容的API修改
    • 次版本号:向后兼容的功能性新增
    • 修订号:向后兼容的问题修正
  2. 发布检查清单

    • 所有测试通过
    • 文档更新完整
    • 版本号更新
    • 变更日志更新
    • 性能测试通过

📄 许可证

本项目采用 MIT 许可证 - 查看 LICENSE 文件了解详情。

🙏 致谢

感谢所有为本项目做出贡献的开发者和用户。

特别感谢:

  • 国密算法库提供者
  • Spring Boot社区
  • 所有测试用户和反馈者

📧 联系我们: tech-support@bskj.com
🌐 官方网站: https://www.bskj.com
📖 在线文档: https://docs.bskj.com/license