|
|
@@ -0,0 +1,257 @@
|
|
|
+package com.usky.license.client;
|
|
|
+
|
|
|
+import com.usky.license.common.CustomLicenseManager;
|
|
|
+import com.usky.license.common.CustomLicenseParam;
|
|
|
+import de.schlichtherle.license.LicenseManager;
|
|
|
+import de.schlichtherle.license.LicenseParam;
|
|
|
+import de.schlichtherle.license.LicenseContent;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+
|
|
|
+import java.io.File;
|
|
|
+import java.nio.file.Files;
|
|
|
+import java.util.TimeZone;
|
|
|
+import java.util.prefs.Preferences;
|
|
|
+import org.springframework.core.env.Environment;
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
+import java.util.Date;
|
|
|
+
|
|
|
+
|
|
|
+@Slf4j
|
|
|
+@Component
|
|
|
+public class LicenseVerify {
|
|
|
+
|
|
|
+ @Value("${license.subject}")
|
|
|
+ private String defaultSubject;
|
|
|
+ @Value("${license.publicAlias}")
|
|
|
+ private String defaultPublicAlias;
|
|
|
+ @Value("${license.storePass}")
|
|
|
+ private String defaultStorePass;
|
|
|
+ @Value("${license.licensePath}")
|
|
|
+ private String defaultLicensePath;
|
|
|
+ @Value("${license.publicKeysStorePath}")
|
|
|
+ private String defaultPublicKeysStorePath;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private Environment env;
|
|
|
+
|
|
|
+ // ========== 新增:读取证书有效期 ==========
|
|
|
+ public void readLicenseExpireTime() {
|
|
|
+ // 1. 获取配置参数
|
|
|
+ String subject = env.getProperty("license.subject");
|
|
|
+ String publicAlias = env.getProperty("license.publicAlias");
|
|
|
+ String storePass = env.getProperty("license.storePass");
|
|
|
+ String licensePath = env.getProperty("license.licensePath");
|
|
|
+ String publicKeysStorePath = env.getProperty("license.publicKeysStorePath");
|
|
|
+
|
|
|
+ // 2. 非空校验
|
|
|
+ if (licensePath == null || licensePath.trim().isEmpty() || !new File(licensePath).exists()) {
|
|
|
+ log.error("证书文件不存在,路径:{}", licensePath);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (publicKeysStorePath == null || publicKeysStorePath.trim().isEmpty()) {
|
|
|
+ log.error("公钥库配置为空");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 3. 构建LicenseParam
|
|
|
+ Preferences preferences = Preferences.userRoot().node(LicenseManager.class.getName());
|
|
|
+ LicenseParam licenseParam = new CustomLicenseParam(
|
|
|
+ subject,
|
|
|
+ preferences,
|
|
|
+ new File(publicKeysStorePath),
|
|
|
+ publicAlias,
|
|
|
+ storePass.toCharArray(),
|
|
|
+ new File(licensePath)
|
|
|
+ );
|
|
|
+
|
|
|
+ // 4. 初始化自定义LicenseManager
|
|
|
+ CustomLicenseManager licenseManager = new CustomLicenseManager(licenseParam);
|
|
|
+
|
|
|
+ // 5. 读取证书字节数组并解析内容
|
|
|
+ byte[] certBytes = Files.readAllBytes(new File(licensePath).toPath());
|
|
|
+ LicenseContent licenseContent = licenseManager.verifyCertificate(certBytes);
|
|
|
+
|
|
|
+ // 6. 获取有效期并格式化输出
|
|
|
+ Date notBefore = licenseContent.getNotBefore(); // 证书生效时间
|
|
|
+ Date notAfter = licenseContent.getNotAfter(); // 证书过期时间
|
|
|
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
|
|
+ sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
|
|
|
+
|
|
|
+ log.info("===== 证书有效期信息 =====");
|
|
|
+ log.info("证书主题:{}", licenseContent.getSubject());
|
|
|
+ log.info("生效时间:{}", sdf.format(notBefore));
|
|
|
+ log.info("过期时间:{}", sdf.format(notAfter));
|
|
|
+ log.info("有效期时长:{} 天", (notAfter.getTime() - notBefore.getTime()) / (1000 * 60 * 60 * 24));
|
|
|
+ log.info("=======================");
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("读取证书有效期失败", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 无参安装(使用默认配置)
|
|
|
+ public boolean install() {
|
|
|
+ File licenseFile = new File(defaultLicensePath);
|
|
|
+ File publicKeysStoreFile = new File(defaultPublicKeysStorePath);
|
|
|
+ return doInstall(defaultSubject, defaultPublicAlias, defaultStorePass, licenseFile, publicKeysStoreFile);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 自定义路径安装
|
|
|
+ public boolean install(String customLicensePath) {
|
|
|
+ File licenseFile = new File(customLicensePath);
|
|
|
+ File publicKeysStoreFile = new File(defaultPublicKeysStorePath);
|
|
|
+ return doInstall(defaultSubject, defaultPublicAlias, defaultStorePass, licenseFile, publicKeysStoreFile);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 自定义参数安装
|
|
|
+ public boolean install(LicenseVerifyParam param) {
|
|
|
+ if (param == null) {
|
|
|
+ log.error("证书安装失败:LicenseVerifyParam参数为null");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ // 参数非空校验
|
|
|
+ if (param.getSubject() == null || param.getSubject().trim().isEmpty()
|
|
|
+ || param.getPublicAlias() == null || param.getPublicAlias().trim().isEmpty()
|
|
|
+ || param.getStorePass() == null || param.getStorePass().trim().isEmpty()
|
|
|
+ || param.getLicensePath() == null || param.getLicensePath().trim().isEmpty()
|
|
|
+ || param.getPublicKeysStorePath() == null || param.getPublicKeysStorePath().trim().isEmpty()) {
|
|
|
+ log.error("证书安装失败:LicenseVerifyParam必要参数为空");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ File licenseFile = new File(param.getLicensePath());
|
|
|
+ File publicKeysStoreFile = new File(param.getPublicKeysStorePath());
|
|
|
+ return doInstall(param.getSubject(), param.getPublicAlias(), param.getStorePass(), licenseFile, publicKeysStoreFile);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 无参验证(此处是报错的核心方法,增加非空校验)
|
|
|
+ public boolean verify() {
|
|
|
+ // 核心:先校验配置参数是否为null,提前报错
|
|
|
+ if (defaultLicensePath == null || defaultLicensePath.trim().isEmpty()) {
|
|
|
+ log.error("证书验证失败:license.licensePath 配置为空请检查");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (defaultPublicKeysStorePath == null || defaultPublicKeysStorePath.trim().isEmpty()) {
|
|
|
+ log.error("证书验证失败:license.publicKeysStorePath 配置为空请检查");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (defaultSubject == null || defaultPublicAlias == null || defaultStorePass == null) {
|
|
|
+ log.error("证书验证失败:subject/publicAlias/storePass 配置为空请检查");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ File licenseFile = new File(defaultLicensePath);
|
|
|
+ File publicKeysStoreFile = new File(defaultPublicKeysStorePath);
|
|
|
+ return doVerify(defaultSubject, defaultPublicAlias, defaultStorePass, licenseFile, publicKeysStoreFile);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 自定义参数验证
|
|
|
+ public boolean verify(LicenseVerifyParam param) {
|
|
|
+ if (param == null) {
|
|
|
+ log.error("证书验证失败:LicenseVerifyParam参数为null");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ // 参数非空校验
|
|
|
+ if (param.getSubject() == null || param.getSubject().trim().isEmpty()
|
|
|
+ || param.getPublicAlias() == null || param.getPublicAlias().trim().isEmpty()
|
|
|
+ || param.getStorePass() == null || param.getStorePass().trim().isEmpty()
|
|
|
+ || param.getLicensePath() == null || param.getLicensePath().trim().isEmpty()
|
|
|
+ || param.getPublicKeysStorePath() == null || param.getPublicKeysStorePath().trim().isEmpty()) {
|
|
|
+ log.error("证书验证失败:LicenseVerifyParam必要参数为空");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ File licenseFile = new File(param.getLicensePath());
|
|
|
+ File publicKeysStoreFile = new File(param.getPublicKeysStorePath());
|
|
|
+ return doVerify(param.getSubject(), param.getPublicAlias(), param.getStorePass(), licenseFile, publicKeysStoreFile);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 核心安装逻辑(验证+缓存)
|
|
|
+ private boolean doInstall(String subject, String publicAlias, String storePass, File licenseFile, File publicKeysStoreFile) {
|
|
|
+ // 文件存在性校验
|
|
|
+ if (!publicKeysStoreFile.exists()) {
|
|
|
+ log.error("证书安装失败:公钥库文件不存在 -> {}", publicKeysStoreFile.getAbsolutePath());
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (!licenseFile.exists()) {
|
|
|
+ log.error("证书安装失败:证书文件不存在 -> {}", licenseFile.getAbsolutePath());
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 1. 构建LicenseParam(TrueLicense必要参数)
|
|
|
+ Preferences preferences = Preferences.userRoot().node(LicenseManager.class.getName());
|
|
|
+ LicenseParam licenseParam = new CustomLicenseParam(
|
|
|
+ subject,
|
|
|
+ preferences,
|
|
|
+ publicKeysStoreFile,
|
|
|
+ publicAlias,
|
|
|
+ storePass.toCharArray(),
|
|
|
+ licenseFile
|
|
|
+ );
|
|
|
+
|
|
|
+ // 2. 初始化自定义LicenseManager
|
|
|
+ CustomLicenseManager licenseManager = new CustomLicenseManager(licenseParam);
|
|
|
+
|
|
|
+ // 3. 读取证书字节数组(无需补位,明文签名证书)
|
|
|
+ byte[] certBytes = Files.readAllBytes(licenseFile.toPath());
|
|
|
+
|
|
|
+ // 4. 调用公共包装方法(核心!解决权限问题)
|
|
|
+ LicenseContent content = licenseManager.verifyCertificate(certBytes);
|
|
|
+
|
|
|
+ if (content != null) {
|
|
|
+ log.info("===== 证书安装(验证)成功 =====");
|
|
|
+ return true;
|
|
|
+ } else {
|
|
|
+ log.error("===== 证书安装失败:证书内容为空 =====");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("===== 证书安装失败 =====", e);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 核心验证逻辑
|
|
|
+ private boolean doVerify(String subject, String publicAlias, String storePass, File licenseFile, File publicKeysStoreFile) {
|
|
|
+ // 文件存在性校验
|
|
|
+ if (!publicKeysStoreFile.exists()) {
|
|
|
+ log.error("证书验证失败:公钥库文件不存在 -> {}", publicKeysStoreFile.getAbsolutePath());
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (!licenseFile.exists()) {
|
|
|
+ log.error("证书验证失败:证书文件不存在 -> {}", licenseFile.getAbsolutePath());
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 1. 构建LicenseParam(TrueLicense必要参数)
|
|
|
+ Preferences preferences = Preferences.userRoot().node(LicenseManager.class.getName());
|
|
|
+ LicenseParam licenseParam = new CustomLicenseParam(
|
|
|
+ subject,
|
|
|
+ preferences,
|
|
|
+ publicKeysStoreFile,
|
|
|
+ publicAlias,
|
|
|
+ storePass.toCharArray(),
|
|
|
+ licenseFile
|
|
|
+ );
|
|
|
+
|
|
|
+ // 2. 初始化自定义LicenseManager
|
|
|
+ CustomLicenseManager licenseManager = new CustomLicenseManager(licenseParam);
|
|
|
+
|
|
|
+ // 3. 读取证书字节数组(无需补位,明文签名证书)
|
|
|
+ byte[] certBytes = Files.readAllBytes(licenseFile.toPath());
|
|
|
+
|
|
|
+ // 4. 调用公共包装方法(核心!解决权限问题)
|
|
|
+ licenseManager.verifyCertificate(certBytes);
|
|
|
+
|
|
|
+ log.info("===== 证书验证成功 =====");
|
|
|
+ return true;
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("===== 证书验证失败 =====", e);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|