package com.estate.expert.admin.utils; import com.estate.expert.admin.enums.BizResultCode; import com.estate.expert.common.exception.BizException; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.Base64; import java.util.logging.Logger; /** * License验证工具类 * 用于系统license的加密、解密和验证 * 当license过期时,系统将停止运行 */ public class License { private static final Logger logger = Logger.getLogger(License.class.getName()); // 加密密钥(实际使用时应该从配置文件或环境变量中读取) // AES密钥必须是16、24或32字节长度 private static final String SECRET_KEY = "EstateExpert2024Key32BytesForAES"; // License密钥(从配置文件读取) private static String LICENSE_KEY; // 加密算法 private static final String ALGORITHM = "AES"; // 日期格式 private static final String DATE_FORMAT = "yyyy-MM-dd"; // 系统启动时间 private static LocalDate systemStartDate; // License过期日期 private static LocalDate licenseExpiryDate; // License是否有效 private static boolean isLicenseValid = false; // 静态初始化块,验证密钥 static { if (!validateKey()) { logger.severe("License系统初始化失败:密钥长度不正确"); } } /** * 设置License密钥(从配置文件读取) * @param licenseKey License密钥 */ public static void setLicenseKey(String licenseKey) { LICENSE_KEY = licenseKey; // logger.info("License密钥已设置"); } /** * 初始化License验证(使用配置文件中的密钥) * @throws BizException 当License验证失败时抛出 */ public static void initializeLicenseFromConfig() { if (LICENSE_KEY == null || LICENSE_KEY.trim().isEmpty()) { logger.severe("License密钥未设置,系统无法启动"); throw new BizException(BizResultCode.LICENSE_NOT_CONFIGURED); } if (!initializeLicense(LICENSE_KEY)) { throw new BizException(BizResultCode.LICENSE_VALIDATION_FAILED); } } /** * 验证密钥长度 * @return 密钥是否有效 */ private static boolean validateKey() { byte[] keyBytes = SECRET_KEY.getBytes(StandardCharsets.UTF_8); if (keyBytes.length != 32) { logger.severe("密钥长度不正确,需要32字节,当前: " + keyBytes.length + " 字节"); return false; } return true; } /** * 初始化License验证 * @param encryptedLicense 加密的license字符串 * @return 是否初始化成功 */ public static boolean initializeLicense(String encryptedLicense) { try { if (encryptedLicense == null || encryptedLicense.trim().isEmpty()) { logger.severe("License字符串为空,系统无法启动"); BizResultCode.LICENSE_NOT_CONFIGURED.check(true); return false; } // 解密license String decryptedLicense = decrypt(encryptedLicense); if (decryptedLicense == null) { logger.severe("License解密失败,系统无法启动"); BizResultCode.LICENSE_VALIDATION_FAILED.check(true); return false; } // 解析license信息 String[] licenseParts = decryptedLicense.split("\\|"); if (licenseParts.length != 3) { logger.severe("License格式错误,系统无法启动"); BizResultCode.LICENSE_INVALID_FORMAT.check(true); return false; } // 验证license签名 String licenseData = licenseParts[0] + "|" + licenseParts[1]; String signature = licenseParts[2]; if (!verifySignature(licenseData, signature)) { logger.severe("License签名验证失败,系统无法启动"); BizResultCode.LICENSE_SIGNATURE_INVALID.check(true); return false; } // 解析过期日期 DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT); licenseExpiryDate = LocalDate.parse(licenseParts[1], formatter); systemStartDate = LocalDate.now(); // 检查license是否过期 if (isLicenseExpired()) { logger.severe("License已过期,系统无法启动"); BizResultCode.LICENSE_EXPIRED.check(true); return false; } isLicenseValid = true; logger.info("启动验证,系统启动时间: " + systemStartDate + ", 过期时间: " + licenseExpiryDate); return true; } catch (BizException e) { // 重新抛出BizException throw e; } catch (Exception e) { logger.severe("License初始化失败: " + e.getMessage()); BizResultCode.LICENSE_VALIDATION_FAILED.check(true); return false; } } /** * 检查License是否有效 * @return 是否有效 */ public static boolean isLicenseValid() { if (!isLicenseValid) { return false; } // 检查是否过期 if (isLicenseExpired()) { logger.severe("License已过期,系统将停止运行"); isLicenseValid = false; return false; } return true; } /** * 验证License有效性,如果无效则抛出异常 * @throws BizException 当License无效时抛出 */ public static void validateLicense() { if (!isLicenseValid()) { throw new BizException(BizResultCode.LICENSE_EXPIRED); } } /** * 检查License是否过期 * @return 是否过期 */ public static boolean isLicenseExpired() { if (licenseExpiryDate == null) { return true; } LocalDate currentDate = LocalDate.now(); return currentDate.isAfter(licenseExpiryDate); } /** * 获取剩余天数 * @return 剩余天数,-1表示已过期 */ public static long getRemainingDays() { if (licenseExpiryDate == null) { return -1; } LocalDate currentDate = LocalDate.now(); if (currentDate.isAfter(licenseExpiryDate)) { return -1; } return java.time.temporal.ChronoUnit.DAYS.between(currentDate, licenseExpiryDate); } /** * 生成License * @param expiryDate 过期日期 * @return 加密的license字符串 */ public static String generateLicense(LocalDate expiryDate) { try { String licenseData = "EstateExpert|" + expiryDate.format(DateTimeFormatter.ofPattern(DATE_FORMAT)); String signature = generateSignature(licenseData); String fullLicense = licenseData + "|" + signature; return encrypt(fullLicense); } catch (Exception e) { logger.severe("生成License失败: " + e.getMessage()); return null; } } /** * 加密字符串 * @param plainText 明文 * @return 加密后的字符串 */ private static String encrypt(String plainText) { try { if (!validateKey()) { return null; } SecretKeySpec secretKey = new SecretKeySpec(SECRET_KEY.getBytes(StandardCharsets.UTF_8), ALGORITHM); Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, secretKey); byte[] encryptedBytes = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8)); return Base64.getEncoder().encodeToString(encryptedBytes); } catch (Exception e) { logger.severe("加密失败: " + e.getMessage()); return null; } } /** * 解密字符串 * @param encryptedText 加密的字符串 * @return 解密后的字符串 */ private static String decrypt(String encryptedText) { try { if (!validateKey()) { return null; } SecretKeySpec secretKey = new SecretKeySpec(SECRET_KEY.getBytes(StandardCharsets.UTF_8), ALGORITHM); Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, secretKey); byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedText)); return new String(decryptedBytes, StandardCharsets.UTF_8); } catch (Exception e) { logger.severe("解密失败: " + e.getMessage()); return null; } } /** * 生成签名 * @param data 数据 * @return 签名 */ private static String generateSignature(String data) { try { MessageDigest digest = MessageDigest.getInstance("SHA-256"); byte[] hash = digest.digest((data + SECRET_KEY).getBytes(StandardCharsets.UTF_8)); return Base64.getEncoder().encodeToString(hash); } catch (Exception e) { logger.severe("生成签名失败: " + e.getMessage()); return null; } } /** * 验证签名 * @param data 数据 * @param signature 签名 * @return 是否验证通过 */ private static boolean verifySignature(String data, String signature) { try { String expectedSignature = generateSignature(data); return expectedSignature != null && expectedSignature.equals(signature); } catch (Exception e) { logger.severe("验证签名失败: " + e.getMessage()); return false; } } /** * 强制停止系统 */ public static void forceSystemShutdown() { logger.severe("License验证失败,系统强制停止运行"); System.exit(1); } /** * 获取License信息 * @return License信息字符串 */ public static String getLicenseInfo() { if (!isLicenseValid) { return "License无效"; } StringBuilder info = new StringBuilder(); info.append("系统启动时间: ").append(systemStartDate).append("\n"); info.append("License过期时间: ").append(licenseExpiryDate).append("\n"); info.append("剩余天数: ").append(getRemainingDays()).append("\n"); info.append("License状态: ").append(isLicenseExpired() ? "已过期" : "有效"); return info.toString(); } /** * 测试方法 - 生成测试License * @param args 命令行参数 */ public static void main(String[] args) { try { System.out.println("=== License验证系统测试 ==="); // 生成一个30天后过期的License // LocalDate expiryDate = LocalDate.now().plusDays(-10); LocalDate expiryDate = LocalDate.now().plusDays(199999); String license = generateLicense(expiryDate); if (license == null) { System.err.println("生成License失败"); return; } System.out.println("生成的License: " + license); System.out.println("过期日期: " + expiryDate); System.out.println(); // 测试License验证 System.out.println("开始验证License..."); boolean isValid = initializeLicense(license); System.out.println("License验证结果: " + isValid); if (isValid) { System.out.println("License信息:"); System.out.println(getLicenseInfo()); // 测试License有效性检查 System.out.println("\n当前License是否有效: " + isLicenseValid()); System.out.println("剩余天数: " + getRemainingDays()); } else { System.err.println("License验证失败,系统无法启动"); } } catch (Exception e) { System.err.println("测试过程中发生错误: " + e.getMessage()); e.printStackTrace(); } } }