diff --git a/wfc-common/wfc-common-license/src/main/java/org/wfc/common/license/CustomLicenseManager.java b/wfc-common/wfc-common-license/src/main/java/org/wfc/common/license/CustomLicenseManager.java index a187d2d..eed62fd 100644 --- a/wfc-common/wfc-common-license/src/main/java/org/wfc/common/license/CustomLicenseManager.java +++ b/wfc-common/wfc-common-license/src/main/java/org/wfc/common/license/CustomLicenseManager.java @@ -10,13 +10,17 @@ import de.schlichtherle.xml.GenericCertificate; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.wfc.common.license.domain.LicenseCheckModel; +import org.wfc.common.license.domain.LicenseConstants; import org.wfc.common.license.serverinfo.AbstractServerInfos; import org.wfc.common.license.serverinfo.LinuxServerInfos; import org.wfc.common.license.serverinfo.WindowsServerInfos; +import org.wfc.common.license.utils.LicenseUtils; import java.beans.XMLDecoder; import java.io.BufferedInputStream; +import java.io.BufferedReader; import java.io.ByteArrayInputStream; +import java.io.FileReader; import java.io.UnsupportedEncodingException; import java.util.Date; import java.util.List; @@ -171,8 +175,30 @@ public class CustomLicenseManager extends LicenseManager { throw new LicenseContentException("不能获取服务器硬件信息"); } } + // 校验服务器时间是否被篡改 + if (!verityTimeFile()) { + throw new LicenseContentException("当前服务器的时间不正常"); + } } + private boolean verityTimeFile() { + try { + // 取出时间文件 + BufferedReader reader = new BufferedReader(new FileReader(LicenseConstants.TIME_PATH)); + String fileJson = reader.readLine(); + reader.close(); + String decryptedJson = LicenseUtils.decrypt(fileJson); + if (Long.parseLong(decryptedJson) < System.currentTimeMillis()) { + return true; + } + } catch (Exception e) { + log.error("verity license time error", e); + return false; + } + return false; + } + + /** * 重写XMLDecoder解析XML diff --git a/wfc-common/wfc-common-license/src/main/java/org/wfc/common/license/domain/LicenseConstants.java b/wfc-common/wfc-common-license/src/main/java/org/wfc/common/license/domain/LicenseConstants.java new file mode 100644 index 0000000..1b1a183 --- /dev/null +++ b/wfc-common/wfc-common-license/src/main/java/org/wfc/common/license/domain/LicenseConstants.java @@ -0,0 +1,12 @@ +package org.wfc.common.license.domain; + +/** + * @author: cyc + * @since: 2025-04-27 + */ +public class LicenseConstants { + + public final static String TIME_PATH = "/var/lib/pro/etc/serve/production.json"; + + public static final String KEY = "wfcwanfiAdmin6666"; +} diff --git a/wfc-common/wfc-common-license/src/main/java/org/wfc/common/license/runner/LicenseCheckRunner.java b/wfc-common/wfc-common-license/src/main/java/org/wfc/common/license/runner/LicenseCheckRunner.java index f5a3ea6..21b6fe1 100644 --- a/wfc-common/wfc-common-license/src/main/java/org/wfc/common/license/runner/LicenseCheckRunner.java +++ b/wfc-common/wfc-common-license/src/main/java/org/wfc/common/license/runner/LicenseCheckRunner.java @@ -10,18 +10,17 @@ import org.springframework.boot.ApplicationRunner; import org.springframework.stereotype.Component; import org.wfc.common.license.LicenseVerify; import org.wfc.common.license.domain.LicenseCheckModel; +import org.wfc.common.license.domain.LicenseConstants; import org.wfc.common.license.domain.LicenseVerifyParam; import org.wfc.common.license.serverinfo.AbstractServerInfos; +import org.wfc.common.license.utils.LicenseUtils; -import javax.crypto.Cipher; -import javax.crypto.spec.SecretKeySpec; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileWriter; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.util.Base64; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; @@ -38,12 +37,10 @@ public class LicenseCheckRunner implements ApplicationRunner { private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); private ScheduledFuture scheduledFuture; - private static final String key = "wfcwanfiAdmin6666"; - - // 启动定时任务 public void startTimer() { scheduledFuture = scheduler.scheduleAtFixedRate(this::timer, 0, 30, TimeUnit.SECONDS); + scheduler.scheduleAtFixedRate(this::fileTimer, 0, 60, TimeUnit.SECONDS); } // 停止定时任务 @@ -100,7 +97,13 @@ public class LicenseCheckRunner implements ApplicationRunner { install(); LicenseCheckRunner.md5 = readMd5; } + } + /** + * 5秒检测一次,不能太快也不能太慢 + */ + protected void fileTimer() { + createTimeFile(); } private void install() { @@ -131,10 +134,10 @@ public class LicenseCheckRunner implements ApplicationRunner { String jsonString = serverInfos.toJsonString(); System.out.println("原始数据 = " + jsonString); //加密 - String encryptedJson = encrypt(jsonString); + String encryptedJson = LicenseUtils.encrypt(jsonString); System.out.println("加密后 = " + encryptedJson); // 解密 - String decryptedJson = decrypt(encryptedJson); + String decryptedJson = LicenseUtils.decrypt(encryptedJson); System.out.println("解密后 = " + decryptedJson); // 比较解密后的字符串与原始字符串 if (jsonString.equals(decryptedJson)) { @@ -156,38 +159,22 @@ public class LicenseCheckRunner implements ApplicationRunner { FileWriter writer = new FileWriter(licenseProperties.getCodePath()); writer.write(encryptedJson); writer.close(); - log.info("licenseParam {}", licenseParam); + log.debug("licenseParam {}", licenseParam); } catch (Exception e) { log.error("生成激活码失败", e); } } - - private String encrypt(String json) throws Exception { - byte[] keyBytes = key.getBytes(); - MessageDigest sha = MessageDigest.getInstance("SHA-256"); - keyBytes = sha.digest(keyBytes); - keyBytes = java.util.Arrays.copyOf(keyBytes, 16); - SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "AES"); - - Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING"); - cipher.init(Cipher.ENCRYPT_MODE, secretKey); - byte[] encryptedBytes = cipher.doFinal(json.getBytes()); - return Base64.getEncoder().encodeToString(encryptedBytes); - } - - private String decrypt(String encryptedJson) throws Exception { - byte[] keyBytes = key.getBytes(); - MessageDigest sha = MessageDigest.getInstance("SHA-256"); - keyBytes = sha.digest(keyBytes); - keyBytes = java.util.Arrays.copyOf(keyBytes, 16); - SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "AES"); - - Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING"); - cipher.init(Cipher.DECRYPT_MODE, secretKey); - byte[] encryptedBytes = Base64.getDecoder().decode(encryptedJson); - byte[] decryptedBytes = cipher.doFinal(encryptedBytes); - return new String(decryptedBytes); + private void createTimeFile() { + try { + String currentTime = System.currentTimeMillis() + ""; + String encryptedJson = LicenseUtils.encrypt(currentTime); + FileWriter writer = new FileWriter(LicenseConstants.TIME_PATH); + writer.write(encryptedJson); + writer.close(); + } catch (Exception e) { + log.error("license create temp error", e); + } } /** diff --git a/wfc-common/wfc-common-license/src/main/java/org/wfc/common/license/utils/LicenseUtils.java b/wfc-common/wfc-common-license/src/main/java/org/wfc/common/license/utils/LicenseUtils.java new file mode 100644 index 0000000..9ddea93 --- /dev/null +++ b/wfc-common/wfc-common-license/src/main/java/org/wfc/common/license/utils/LicenseUtils.java @@ -0,0 +1,42 @@ +package org.wfc.common.license.utils; + +import org.wfc.common.license.domain.LicenseConstants; + +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; +import java.security.MessageDigest; +import java.util.Base64; + +/** + * @author: cyc + * @since: 2025-04-27 + */ +public class LicenseUtils { + + public static String encrypt(String json) throws Exception { + byte[] keyBytes = LicenseConstants.KEY.getBytes(); + MessageDigest sha = MessageDigest.getInstance("SHA-256"); + keyBytes = sha.digest(keyBytes); + keyBytes = java.util.Arrays.copyOf(keyBytes, 16); + SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "AES"); + + Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING"); + cipher.init(Cipher.ENCRYPT_MODE, secretKey); + byte[] encryptedBytes = cipher.doFinal(json.getBytes()); + return Base64.getEncoder().encodeToString(encryptedBytes); + } + + public static String decrypt(String encryptedJson) throws Exception { + byte[] keyBytes = LicenseConstants.KEY.getBytes(); + MessageDigest sha = MessageDigest.getInstance("SHA-256"); + keyBytes = sha.digest(keyBytes); + keyBytes = java.util.Arrays.copyOf(keyBytes, 16); + SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "AES"); + + Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING"); + cipher.init(Cipher.DECRYPT_MODE, secretKey); + byte[] encryptedBytes = Base64.getDecoder().decode(encryptedJson); + byte[] decryptedBytes = cipher.doFinal(encryptedBytes); + return new String(decryptedBytes); + } +}