From 06f5a0f34680c93efe525b8102d24622b8b20893 Mon Sep 17 00:00:00 2001 From: liquor <958142070@qq.com> Date: Thu, 17 Apr 2025 11:58:52 +0000 Subject: [PATCH] =?UTF-8?q?feat(license):=20=E5=A2=9E=E5=8A=A0=E6=A0=B8?= =?UTF-8?q?=E5=BF=83=E6=A8=A1=E5=9D=97=EF=BC=8C=E4=BC=98=E5=8C=96=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- continew-starter-bom/pom.xml | 9 + .../continew-starter-license-core/pom.xml | 33 ++ .../license/exception/LicenseException.java | 27 +- .../license/model/BuildCreatorResp.java | 68 ++++ .../continew/license/model}/ConfigParam.java | 12 +- .../license/model}/CustomKeyStoreParam.java | 31 +- .../license/model}/LicenseCreatorParam.java | 48 ++- .../license/model}/LicenseCreatorParamVO.java | 26 +- .../license/model}/LicenseExtraModel.java | 10 +- .../continew/license/util/ExecCmdUtil.java | 22 +- .../license/util/ServerInfoUtils.java | 60 ++-- .../README.md | 4 +- .../continew-starter-license-generate/pom.xml | 18 +- .../LicenseGenerateAutoConfiguration.java | 2 +- .../LicenseGenerateProperties.java | 2 +- .../top/continew/license/dto/ConfigParam.java | 59 --- .../keyStoreParam/CustomKeyStoreParam.java | 71 ---- .../license/manager/ServerLicenseManager.java | 24 +- .../license/service/LicenseCreateService.java | 224 ++++++------ .../continew-starter-license-verify/pom.xml | 17 +- .../LicenseStarterInitializingBean.java | 4 +- .../LicenseVerifyAutoConfiguration.java | 19 +- .../LicenseVerifyProperties.java | 4 +- .../license/bean/LicenseInstallerBean.java | 68 ++-- .../license/dto/LicenseExtraModel.java | 83 ----- .../license/exception/VerifyException.java | 32 -- .../license/manager/CustomLicenseManager.java | 143 ++++---- .../license/utils/ServerInfoUtils.java | 338 ------------------ continew-starter-license/pom.xml | 11 +- 29 files changed, 515 insertions(+), 954 deletions(-) create mode 100644 continew-starter-license/continew-starter-license-core/pom.xml rename continew-starter-license/{continew-starter-license-generate => continew-starter-license-core}/src/main/java/top/continew/license/exception/LicenseException.java (62%) create mode 100644 continew-starter-license/continew-starter-license-core/src/main/java/top/continew/license/model/BuildCreatorResp.java rename continew-starter-license/{continew-starter-license-verify/src/main/java/top/continew/license/dto => continew-starter-license-core/src/main/java/top/continew/license/model}/ConfigParam.java (90%) rename continew-starter-license/{continew-starter-license-verify/src/main/java/top/continew/license/keyStoreParam => continew-starter-license-core/src/main/java/top/continew/license/model}/CustomKeyStoreParam.java (76%) rename continew-starter-license/{continew-starter-license-generate/src/main/java/top/continew/license/dto => continew-starter-license-core/src/main/java/top/continew/license/model}/LicenseCreatorParam.java (87%) rename continew-starter-license/{continew-starter-license-generate/src/main/java/top/continew/license/dto => continew-starter-license-core/src/main/java/top/continew/license/model}/LicenseCreatorParamVO.java (94%) rename continew-starter-license/{continew-starter-license-generate/src/main/java/top/continew/license/dto => continew-starter-license-core/src/main/java/top/continew/license/model}/LicenseExtraModel.java (92%) rename continew-starter-license/{continew-starter-license-generate => continew-starter-license-core}/src/main/java/top/continew/license/util/ExecCmdUtil.java (88%) rename continew-starter-license/{continew-starter-license-generate => continew-starter-license-core}/src/main/java/top/continew/license/util/ServerInfoUtils.java (85%) delete mode 100644 continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/dto/ConfigParam.java delete mode 100644 continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/keyStoreParam/CustomKeyStoreParam.java delete mode 100644 continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/dto/LicenseExtraModel.java delete mode 100644 continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/exception/VerifyException.java delete mode 100644 continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/utils/ServerInfoUtils.java diff --git a/continew-starter-bom/pom.xml b/continew-starter-bom/pom.xml index ffb0dbb8..2a1b9cdd 100644 --- a/continew-starter-bom/pom.xml +++ b/continew-starter-bom/pom.xml @@ -276,12 +276,21 @@ continew-starter-core ${revision} + + + + top.continew + continew-starter-license-core + ${revision} + + top.continew continew-starter-license-generate ${revision} + top.continew diff --git a/continew-starter-license/continew-starter-license-core/pom.xml b/continew-starter-license/continew-starter-license-core/pom.xml new file mode 100644 index 00000000..8a7d1922 --- /dev/null +++ b/continew-starter-license/continew-starter-license-core/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + + top.continew + continew-starter-license + ${revision} + + continew-starter-license-core + ContiNew Starter License核心模块 + + + + + top.continew + continew-starter-core + + + + + de.schlichtherle.truelicense + truelicense-core + + + + + net.lingala.zip4j + zip4j + + + + diff --git a/continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/exception/LicenseException.java b/continew-starter-license/continew-starter-license-core/src/main/java/top/continew/license/exception/LicenseException.java similarity index 62% rename from continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/exception/LicenseException.java rename to continew-starter-license/continew-starter-license-core/src/main/java/top/continew/license/exception/LicenseException.java index bbc7ee6e..106084f4 100644 --- a/continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/exception/LicenseException.java +++ b/continew-starter-license/continew-starter-license-core/src/main/java/top/continew/license/exception/LicenseException.java @@ -16,17 +16,34 @@ package top.continew.license.exception; +import top.continew.starter.core.exception.BaseException; + +import java.io.Serial; + /** * 自定义证书认证异常 * - * @Desc: - * @Author loach - * @ClassName top.continew.license.exception.LicenseException - * @Date 2025-03-21 14:30 + * @author loach + * @author echo + * @since 2.11.0 */ -public class LicenseException extends RuntimeException { +public class LicenseException extends BaseException { + + @Serial + private static final long serialVersionUID = 1L; + + public LicenseException() { + } public LicenseException(String message) { super(message); } + + public LicenseException(Throwable cause) { + super(cause); + } + + public LicenseException(String message, Throwable cause) { + super(message, cause); + } } diff --git a/continew-starter-license/continew-starter-license-core/src/main/java/top/continew/license/model/BuildCreatorResp.java b/continew-starter-license/continew-starter-license-core/src/main/java/top/continew/license/model/BuildCreatorResp.java new file mode 100644 index 00000000..5e11695e --- /dev/null +++ b/continew-starter-license/continew-starter-license-core/src/main/java/top/continew/license/model/BuildCreatorResp.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. + *

+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.gnu.org/licenses/lgpl.html + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package top.continew.license.model; + +import net.lingala.zip4j.ZipFile; + +import java.io.Serial; +import java.io.Serializable; + +/** + * 生成创建者返回参数 + * + * @author echo + * @since 2.11.0 + **/ +public class BuildCreatorResp implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 许可证创建者参数 + */ + private LicenseCreatorParam param; + + /** + * 客户端zip文件 + */ + private ZipFile clientZipFile; + + public BuildCreatorResp(LicenseCreatorParam param, ZipFile clientZipFile) { + this.param = param; + this.clientZipFile = clientZipFile; + } + + public BuildCreatorResp() { + } + + public LicenseCreatorParam getParam() { + return param; + } + + public void setParam(LicenseCreatorParam param) { + this.param = param; + } + + public ZipFile getClientZipFile() { + return clientZipFile; + } + + public void setClientZipFile(ZipFile clientZipFile) { + this.clientZipFile = clientZipFile; + } +} diff --git a/continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/dto/ConfigParam.java b/continew-starter-license/continew-starter-license-core/src/main/java/top/continew/license/model/ConfigParam.java similarity index 90% rename from continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/dto/ConfigParam.java rename to continew-starter-license/continew-starter-license-core/src/main/java/top/continew/license/model/ConfigParam.java index 9f9d3331..2c06d2fd 100644 --- a/continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/dto/ConfigParam.java +++ b/continew-starter-license/continew-starter-license-core/src/main/java/top/continew/license/model/ConfigParam.java @@ -14,14 +14,14 @@ * limitations under the License. */ -package top.continew.license.dto; +package top.continew.license.model; /** - * @Desc: - * @Author loach - * @ClassName top.continew.license.dto.ConfigParam - * @Date 2025-03-21 14:50 - */ + * config参数 + * + * @author loach + * @since 2.11.0 + **/ public class ConfigParam { /** diff --git a/continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/keyStoreParam/CustomKeyStoreParam.java b/continew-starter-license/continew-starter-license-core/src/main/java/top/continew/license/model/CustomKeyStoreParam.java similarity index 76% rename from continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/keyStoreParam/CustomKeyStoreParam.java rename to continew-starter-license/continew-starter-license-core/src/main/java/top/continew/license/model/CustomKeyStoreParam.java index f91a5e8e..da3e37a6 100644 --- a/continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/keyStoreParam/CustomKeyStoreParam.java +++ b/continew-starter-license/continew-starter-license-core/src/main/java/top/continew/license/model/CustomKeyStoreParam.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package top.continew.license.keyStoreParam; +package top.continew.license.model; import de.schlichtherle.license.AbstractKeyStoreParam; @@ -23,24 +23,37 @@ import java.io.IOException; import java.io.InputStream; /** - * @Desc: - * @Author loach - * @ClassName top.continew.license.keyStoreParam.CustomKeyStoreParam - * @Date 2025-04-12 14:50 + * 自定义密钥存储参数 + * + * @author loach + * @author echo + * @since 2.11.0 */ public class CustomKeyStoreParam extends AbstractKeyStoreParam { - /** 密钥路径,可为磁盘路径,也可为项目资源文件里的路径,如果为磁盘路径需重写getStream()方法 */ + /** + * 密钥路径,可为磁盘路径,也可为项目资源文件里的路径,如果为磁盘路径需重写getStream()方法 + */ private String storePath; - /** 公钥或私钥的别名 */ + /** + * 公钥或私钥的别名 + */ private String alias; - /** 访问公钥/私钥库的密码 */ + /** + * 访问公钥/私钥库的密码 + */ private String storePass; - /** 公钥/私钥的密码 */ + /** + * 公钥/私钥的密码 + */ private String keyPass; + public CustomKeyStoreParam(Class aClass, String s) { + super(aClass, s); + } + public CustomKeyStoreParam(Class clazz, String resource, String alias, String storePass, String keyPass) { super(clazz, resource); this.storePath = resource; diff --git a/continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/dto/LicenseCreatorParam.java b/continew-starter-license/continew-starter-license-core/src/main/java/top/continew/license/model/LicenseCreatorParam.java similarity index 87% rename from continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/dto/LicenseCreatorParam.java rename to continew-starter-license/continew-starter-license-core/src/main/java/top/continew/license/model/LicenseCreatorParam.java index 21c17182..b5822f62 100644 --- a/continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/dto/LicenseCreatorParam.java +++ b/continew-starter-license/continew-starter-license-core/src/main/java/top/continew/license/model/LicenseCreatorParam.java @@ -14,42 +14,56 @@ * limitations under the License. */ -package top.continew.license.dto; +package top.continew.license.model; import java.io.Serial; import java.io.Serializable; import java.util.Date; /** - * @Desc: - * @Author loach - * @ClassName top.continew.license.dto.LicenseCreatorParam - * @Date 2025-03-21 14:22 - */ + * 许可证创建者参数 + * + * @author loach + * @since 2.11.0 + **/ public class LicenseCreatorParam implements Serializable { @Serial private static final long serialVersionUID = 1L; - /** 证书主题 */ + /** + * 证书主题 + */ private String subject; - /** 私钥别称 */ + /** + * 私钥别称 + */ private String privateAlias; - /** 私钥密码 */ + /** + * 私钥密码 + */ private String keyPass; - /** 访问公钥库的密码 */ + /** + * 访问公钥库的密码 + */ private String storePass; - /** 证书生成路径 */ + /** + * 证书生成路径 + */ private String licensePath; - /** 私钥库存储路径 */ + /** + * 私钥库存储路径 + */ private String privateKeysStorePath; - /** 证书生效时间 */ + /** + * 证书生效时间 + */ private Date issuedTime = new Date(); /** @@ -67,10 +81,14 @@ public class LicenseCreatorParam implements Serializable { */ private Integer consumerAmount = 1; - /** 描述信息 */ + /** + * 描述信息 + */ private String description; - /** 额外的服务器硬件校验信息 */ + /** + * 额外的服务器硬件校验信息 + */ private LicenseExtraModel licenseExtraModel; public String getSubject() { diff --git a/continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/dto/LicenseCreatorParamVO.java b/continew-starter-license/continew-starter-license-core/src/main/java/top/continew/license/model/LicenseCreatorParamVO.java similarity index 94% rename from continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/dto/LicenseCreatorParamVO.java rename to continew-starter-license/continew-starter-license-core/src/main/java/top/continew/license/model/LicenseCreatorParamVO.java index 137834a8..d7cfd2b0 100644 --- a/continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/dto/LicenseCreatorParamVO.java +++ b/continew-starter-license/continew-starter-license-core/src/main/java/top/continew/license/model/LicenseCreatorParamVO.java @@ -14,18 +14,16 @@ * limitations under the License. */ -package top.continew.license.dto; +package top.continew.license.model; import java.util.Date; /** * 为用户生成证书需要的具体参数 * - * @Desc: - * @Author loach - * @ClassName top.continew.license.dto.LicenseCreatorParamVO - * @Date 2025-03-21 14:29 - */ + * @author loach + * @since 2.11.0 + **/ public class LicenseCreatorParamVO { /** @@ -58,14 +56,6 @@ public class LicenseCreatorParamVO { */ private String licenseSavePath; - public String getLicenseSavePath() { - return licenseSavePath; - } - - public void setLicenseSavePath(String licenseSavePath) { - this.licenseSavePath = licenseSavePath; - } - /** * 额外的服务器硬件校验信息 */ @@ -111,6 +101,14 @@ public class LicenseCreatorParamVO { this.description = description; } + public String getLicenseSavePath() { + return licenseSavePath; + } + + public void setLicenseSavePath(String licenseSavePath) { + this.licenseSavePath = licenseSavePath; + } + public LicenseExtraModel getLicenseExtraModel() { return licenseExtraModel; } diff --git a/continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/dto/LicenseExtraModel.java b/continew-starter-license/continew-starter-license-core/src/main/java/top/continew/license/model/LicenseExtraModel.java similarity index 92% rename from continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/dto/LicenseExtraModel.java rename to continew-starter-license/continew-starter-license-core/src/main/java/top/continew/license/model/LicenseExtraModel.java index 63cfcce3..4d591f56 100644 --- a/continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/dto/LicenseExtraModel.java +++ b/continew-starter-license/continew-starter-license-core/src/main/java/top/continew/license/model/LicenseExtraModel.java @@ -14,18 +14,16 @@ * limitations under the License. */ -package top.continew.license.dto; +package top.continew.license.model; import java.util.Set; /** * 额外的服务器硬件校验信息对象,这里的属性可根据需求自定义 * - * @Desc: - * @Author loach - * @ClassName top.continew.license.dto.LicenseExtraModel - * @Date 2025-03-21 14:28 - */ + * @author loach + * @since 2.11.0 + **/ public class LicenseExtraModel { /** diff --git a/continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/util/ExecCmdUtil.java b/continew-starter-license/continew-starter-license-core/src/main/java/top/continew/license/util/ExecCmdUtil.java similarity index 88% rename from continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/util/ExecCmdUtil.java rename to continew-starter-license/continew-starter-license-core/src/main/java/top/continew/license/util/ExecCmdUtil.java index ea6fb98a..b1823f36 100644 --- a/continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/util/ExecCmdUtil.java +++ b/continew-starter-license/continew-starter-license-core/src/main/java/top/continew/license/util/ExecCmdUtil.java @@ -16,21 +16,19 @@ package top.continew.license.util; +import cn.hutool.core.util.ArrayUtil; + import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.LineNumberReader; -import cn.hutool.core.util.ArrayUtil; - /** * 运行命令行工具类 * - * @Desc: - * @Author loach - * @ClassName top.continew.license.util.ExecCmdUtil - * @Date 2025-03-22 18:44 - */ + * @author loach + * @since 2.11.0 + **/ public class ExecCmdUtil { private static final String CREATE_3RDSESSION_SHELL_SCRIPT = "head -n 80 /dev/urandom | tr -dc A-Za-z0-9 | head -c 168"; @@ -42,8 +40,8 @@ public class ExecCmdUtil { * @return String 返回打印信息 */ public static String exec(String... cmd) throws IOException { - Process process = null; - if (System.getProperty("os.name").indexOf("Windows") != -1) { + Process process; + if (System.getProperty("os.name").contains("Windows")) { if (cmd != null && cmd.length == 1) { process = Runtime.getRuntime().exec(cmd[0]); } else { @@ -59,6 +57,12 @@ public class ExecCmdUtil { return print + " " + err; } + /** + * 读取 InputStream 内容为字符串(使用 GBK 编码)。 + * + * @param in 输入流 + * @return 拼接后的字符串,读取失败返回空字符串 + */ private static String readProcess(InputStream in) { try (LineNumberReader print = new LineNumberReader(new InputStreamReader(in, "GBK"))) { StringBuffer sb = new StringBuffer(); diff --git a/continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/util/ServerInfoUtils.java b/continew-starter-license/continew-starter-license-core/src/main/java/top/continew/license/util/ServerInfoUtils.java similarity index 85% rename from continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/util/ServerInfoUtils.java rename to continew-starter-license/continew-starter-license-core/src/main/java/top/continew/license/util/ServerInfoUtils.java index 89a85fa6..7a424698 100644 --- a/continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/util/ServerInfoUtils.java +++ b/continew-starter-license/continew-starter-license-core/src/main/java/top/continew/license/util/ServerInfoUtils.java @@ -23,8 +23,8 @@ import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.StrUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import top.continew.license.dto.LicenseExtraModel; import top.continew.license.exception.LicenseException; +import top.continew.license.model.LicenseExtraModel; import java.io.*; import java.net.InetAddress; @@ -39,7 +39,7 @@ import java.util.stream.Collectors; * 服务器信息工具类 * * @author Rong.Jia - * @date 2022/03/10 + * @since 2.11.0 */ public class ServerInfoUtils { @@ -55,7 +55,7 @@ public class ServerInfoUtils { /** * 组装需要额外校验的License参数 * - * @return + * @return {@link LicenseExtraModel } */ public static LicenseExtraModel getServerInfos() { LicenseExtraModel result = new LicenseExtraModel(); @@ -75,7 +75,7 @@ public class ServerInfoUtils { /** * 初始化服务器硬件信息,并将信息缓存到内存 * - * @throws Exception 默认异常 + * @throws Exception 例外 */ private static void initServerInfos() throws Exception { if (ServerInfosContainer.ipAddress == null) { @@ -104,7 +104,7 @@ public class ServerInfoUtils { /** * 获取CPU序列号 * - * @return String 主板序列号 + * @return String CPU 序列号 */ public static String getCpuSerial() { return FileUtil.isWindows() ? getWindowCpuSerial() : getLinuxCpuSerial(); @@ -158,15 +158,22 @@ public class ServerInfoUtils { */ private static String getWindowCpuSerial() { - String result = StrUtil.EMPTY; + StringBuilder result = new StringBuilder(StrUtil.EMPTY); File file = null; BufferedReader input = null; try { file = File.createTempFile("tmp", ".vbs"); file.deleteOnExit(); FileWriter fw = new FileWriter(file); - String vbs = "Set objWMIService = GetObject(\"winmgmts:\\\\.\\root\\cimv2\")\n" + "Set colItems = objWMIService.ExecQuery _ \n" + " (\"Select * from Win32_Processor\") \n" + "For Each objItem in colItems \n" + " Wscript.Echo objItem.ProcessorId \n" + " exit for ' do the first cpu only! \n" + "Next \n"; + String vbs = """ + Set objWMIService = GetObject("winmgmts:\\\\.\\root\\cimv2") + Set colItems = objWMIService.ExecQuery("Select * from Win32_Processor") + For Each objItem In colItems + WScript.Echo objItem.ProcessorId + Exit For ' do the first cpu only! + Next + """; fw.write(vbs); fw.close(); @@ -174,7 +181,7 @@ public class ServerInfoUtils { input = new BufferedReader(new InputStreamReader(p.getInputStream())); String line; while ((line = input.readLine()) != null) { - result += line; + result.append(line); } } catch (Exception e) { log.error("获取window cpu信息错误, {}", e.getMessage()); @@ -182,7 +189,7 @@ public class ServerInfoUtils { IoUtil.close(input); FileUtil.del(file); } - return result.trim(); + return result.toString().trim(); } /** @@ -191,23 +198,16 @@ public class ServerInfoUtils { * @return {@link String} */ private static String getLinuxMainBoardSerial() { - String result = StrUtil.EMPTY; - String maniBordCmd = "dmidecode | grep 'Serial Number' | awk '{print $3}' | tail -1"; - BufferedReader br = null; + String command = "dmidecode | grep 'Serial Number' | awk '{print $3}' | tail -1"; try { - Process p = Runtime.getRuntime().exec(new String[] {"sh", "-c", maniBordCmd}); - br = new BufferedReader(new InputStreamReader(p.getInputStream())); - String line; - while ((line = br.readLine()) != null) { - result += line; - break; + Process process = new ProcessBuilder("sh", "-c", command).start(); + try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { + return reader.lines().findFirst().orElse(StrUtil.EMPTY); } } catch (IOException e) { - log.error("获取Linux主板信息错误 {}", e.getMessage()); - } finally { - IoUtil.close(br); + log.error("获取 Linux 主板序列号失败: {}", e.getMessage()); + return StrUtil.EMPTY; } - return result; } /** @@ -216,7 +216,7 @@ public class ServerInfoUtils { * @return {@link String} */ private static String getWindowMainBoardSerial() { - String result = StrUtil.EMPTY; + StringBuilder result = new StringBuilder(StrUtil.EMPTY); File file = null; BufferedReader input = null; try { @@ -224,7 +224,15 @@ public class ServerInfoUtils { file.deleteOnExit(); FileWriter fw = new FileWriter(file); - String vbs = "Set objWMIService = GetObject(\"winmgmts:\\\\.\\root\\cimv2\")\n" + "Set colItems = objWMIService.ExecQuery _ \n" + " (\"Select * from Win32_BaseBoard\") \n" + "For Each objItem in colItems \n" + " Wscript.Echo objItem.SerialNumber \n" + " exit for ' do the first cpu only! \n" + "Next \n"; + String vbs = """ + Set objWMIService = GetObject("winmgmts:\\\\.\\root\\cimv2") + Set colItems = objWMIService.ExecQuery _ + ("Select * from Win32_BaseBoard") + For Each objItem in colItems + Wscript.Echo objItem.SerialNumber + exit for ' do the first cpu only! + Next + """; fw.write(vbs); fw.close(); @@ -232,7 +240,7 @@ public class ServerInfoUtils { input = new BufferedReader(new InputStreamReader(p.getInputStream())); String line; while ((line = input.readLine()) != null) { - result += line; + result.append(line); } } catch (Exception e) { log.error("获取Window主板信息错误 {}", e.getMessage()); @@ -240,7 +248,7 @@ public class ServerInfoUtils { IoUtil.close(input); FileUtil.del(file); } - return result.trim(); + return result.toString().trim(); } /** diff --git a/continew-starter-license/continew-starter-license-generate/README.md b/continew-starter-license/continew-starter-license-generate/README.md index 922cf32f..f2c19670 100644 --- a/continew-starter-license/continew-starter-license-generate/README.md +++ b/continew-starter-license/continew-starter-license-generate/README.md @@ -36,8 +36,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import top.continew.license.dto.LicenseCreatorParamVO; -import top.continew.license.dto.LicenseExtraModel; +import top.continew.license.model.LicenseCreatorParamVO; +import top.continew.license.model.LicenseExtraModel; import top.continew.license.service.LicenseCreateService; import java.util.Calendar; diff --git a/continew-starter-license/continew-starter-license-generate/pom.xml b/continew-starter-license/continew-starter-license-generate/pom.xml index e678f793..b7b7fa1e 100644 --- a/continew-starter-license/continew-starter-license-generate/pom.xml +++ b/continew-starter-license/continew-starter-license-generate/pom.xml @@ -11,25 +11,13 @@ continew-starter-license-generate jar - license 生成模块 基于 truelicens 实现 + ContiNew Starter License生成模块 - + top.continew - continew-starter-log-core - - - - - de.schlichtherle.truelicense - truelicense-core - - - - - net.lingala.zip4j - zip4j + continew-starter-license-core \ No newline at end of file diff --git a/continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/autoconfigure/LicenseGenerateAutoConfiguration.java b/continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/autoconfigure/LicenseGenerateAutoConfiguration.java index 13a61b45..526a8187 100644 --- a/continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/autoconfigure/LicenseGenerateAutoConfiguration.java +++ b/continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/autoconfigure/LicenseGenerateAutoConfiguration.java @@ -32,7 +32,7 @@ import top.continew.starter.core.constant.PropertiesConstants; * license 生成模块 自动配置 * * @author loach - * @since 1.2.0 + * @since 2.11.0 */ @AutoConfiguration @EnableConfigurationProperties(LicenseGenerateProperties.class) diff --git a/continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/autoconfigure/LicenseGenerateProperties.java b/continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/autoconfigure/LicenseGenerateProperties.java index 59592078..6a0a4e1f 100644 --- a/continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/autoconfigure/LicenseGenerateProperties.java +++ b/continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/autoconfigure/LicenseGenerateProperties.java @@ -23,7 +23,7 @@ import top.continew.starter.core.constant.PropertiesConstants; * license 生成模块配置属性 * * @author Jasmine - * @since 1.2.0 + * @since 2.11.0 */ @ConfigurationProperties(PropertiesConstants.LICENSE_GENERATE) public class LicenseGenerateProperties { diff --git a/continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/dto/ConfigParam.java b/continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/dto/ConfigParam.java deleted file mode 100644 index c6fac16d..00000000 --- a/continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/dto/ConfigParam.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. - *

- * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

- * http://www.gnu.org/licenses/lgpl.html - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package top.continew.license.dto; - -/** - * @Desc: - * @Author loach - * @ClassName top.continew.license.dto.ConfigParam - * @Date 2025-03-21 14:50 - */ -public class ConfigParam { - - /** 主题 */ - private String subject; - - /** 公钥别称 */ - private String publicAlias; - - /** 访问公钥库的密码 */ - private String storePass; - - public String getSubject() { - return subject; - } - - public void setSubject(String subject) { - this.subject = subject; - } - - public String getPublicAlias() { - return publicAlias; - } - - public void setPublicAlias(String publicAlias) { - this.publicAlias = publicAlias; - } - - public String getStorePass() { - return storePass; - } - - public void setStorePass(String storePass) { - this.storePass = storePass; - } -} diff --git a/continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/keyStoreParam/CustomKeyStoreParam.java b/continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/keyStoreParam/CustomKeyStoreParam.java deleted file mode 100644 index b06325eb..00000000 --- a/continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/keyStoreParam/CustomKeyStoreParam.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. - *

- * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

- * http://www.gnu.org/licenses/lgpl.html - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package top.continew.license.keyStoreParam; - -import de.schlichtherle.license.AbstractKeyStoreParam; - -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; - -/** - * @Desc: - * @Author loach - * @ClassName top.continew.license.keyStoreParam.CustomKeyStoreParam - * @Date 2025-03-21 14:50 - */ -public class CustomKeyStoreParam extends AbstractKeyStoreParam { - /** 密钥路径,可为磁盘路径,也可为项目资源文件里的路径,如果为磁盘路径需重写getStream()方法 */ - private String storePath; - - /** 公钥或私钥的别名 */ - private String alias; - - /** 访问公钥/私钥库的密码 */ - private String storePass; - - /** 公钥/私钥的密码 */ - private String keyPass; - - public CustomKeyStoreParam(Class clazz, String resource, String alias, String storePass, String keyPass) { - super(clazz, resource); - this.storePath = resource; - this.alias = alias; - this.storePass = storePass; - this.keyPass = keyPass; - } - - @Override - public String getAlias() { - return alias; - } - - @Override - public String getStorePwd() { - return storePass; - } - - @Override - public String getKeyPwd() { - return keyPass; - } - - @Override - public InputStream getStream() throws IOException { - return new FileInputStream(storePath); - } -} diff --git a/continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/manager/ServerLicenseManager.java b/continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/manager/ServerLicenseManager.java index 47ff7e49..2f074e89 100644 --- a/continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/manager/ServerLicenseManager.java +++ b/continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/manager/ServerLicenseManager.java @@ -18,16 +18,16 @@ package top.continew.license.manager; import de.schlichtherle.license.*; import de.schlichtherle.xml.GenericCertificate; +import top.continew.license.exception.LicenseException; import java.util.Date; /** * 自定义服务端证书管理类(生成证书) * - * @Desc: - * @Author loach - * @ClassName top.continew.license.manager.ServerLicenseManager - * @Date 2025-03-22 14:31 + * @author loach + * @author echo + * @since 2.11.0 */ public class ServerLicenseManager extends LicenseManager { @@ -38,27 +38,31 @@ public class ServerLicenseManager extends LicenseManager { /** * 证书生成参数验证 * - * @param content - * @throws LicenseContentException + * @param content 内容 */ - protected synchronized void validateCreate(final LicenseContent content) throws LicenseContentException { + protected synchronized void validateCreate(final LicenseContent content) { Date now = new Date(); Date notBefore = content.getNotBefore(); Date notAfter = content.getNotAfter(); if (notBefore != null && now.before(notBefore)) { - throw new LicenseContentException("证书尚未生效,无法生成"); + throw new LicenseException("证书尚未生效,无法生成"); } if (notAfter != null && now.after(notAfter)) { - throw new LicenseContentException("证书已过期,无法生成"); + throw new LicenseException("证书已过期,无法生成"); } if (notBefore != null && notAfter != null && notBefore.after(notAfter)) { - throw new LicenseContentException("证书生效时间晚于失效时间,无法生成"); + throw new LicenseException("证书生效时间晚于失效时间,无法生成"); } } /** * 重写生成证书的方法,增加生成参数验证 + * + * @param content 内容 + * @param notary 公证人 + * @return {@link byte[] } + * @throws Exception 例外 */ @Override protected synchronized byte[] create(LicenseContent content, LicenseNotary notary) throws Exception { diff --git a/continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/service/LicenseCreateService.java b/continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/service/LicenseCreateService.java index ea84e622..ce798129 100644 --- a/continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/service/LicenseCreateService.java +++ b/continew-starter-license/continew-starter-license-generate/src/main/java/top/continew/license/service/LicenseCreateService.java @@ -16,62 +16,51 @@ package top.continew.license.service; +import cn.hutool.core.util.IdUtil; +import com.fasterxml.jackson.databind.ObjectMapper; +import de.schlichtherle.license.*; +import net.lingala.zip4j.ZipFile; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import top.continew.license.exception.LicenseException; +import top.continew.license.manager.ServerLicenseManager; +import top.continew.license.model.*; +import top.continew.license.util.ExecCmdUtil; +import top.continew.license.util.ServerInfoUtils; + +import javax.security.auth.x500.X500Principal; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Date; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.UUID; import java.util.prefs.Preferences; -import javax.security.auth.x500.X500Principal; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import com.fasterxml.jackson.databind.ObjectMapper; - -import de.schlichtherle.license.CipherParam; -import de.schlichtherle.license.DefaultCipherParam; -import de.schlichtherle.license.DefaultLicenseParam; -import de.schlichtherle.license.KeyStoreParam; -import de.schlichtherle.license.LicenseContent; -import de.schlichtherle.license.LicenseManager; -import de.schlichtherle.license.LicenseParam; -import net.lingala.zip4j.ZipFile; -import top.continew.license.dto.ConfigParam; -import top.continew.license.dto.LicenseCreatorParam; -import top.continew.license.dto.LicenseCreatorParamVO; -import top.continew.license.dto.LicenseExtraModel; -import top.continew.license.exception.LicenseException; -import top.continew.license.keyStoreParam.CustomKeyStoreParam; -import top.continew.license.manager.ServerLicenseManager; -import top.continew.license.util.ExecCmdUtil; -import top.continew.license.util.ServerInfoUtils; - /** * 证书生成接口 实现类 * - * @Desc: - * @Author loach - * @ClassName top.continew.license.service.impl.LicenseCreateServiceImpl - * @Date 2025-03-22 18:36 - */ -@Component + * @author loach + * @since 2.11.0 + **/ + public class LicenseCreateService { private static final Logger log = LoggerFactory.getLogger(LicenseCreateService.class); private static volatile LicenseCreateService instance; + private static final X500Principal DEFAULT_HOLDER_ISSUER = new X500Principal("CN=localhost, OU=localhost, O=localhost, L=SH, ST=SH, C=CN"); + private LicenseCreateService() { - // 私有构造 } + /** + * 获取实例 + * + * @return {@link LicenseCreateService } + */ public static LicenseCreateService getInstance() { if (instance == null) { synchronized (LicenseCreateService.class) { @@ -83,135 +72,115 @@ public class LicenseCreateService { return instance; } - private static final X500Principal DEFAULT_HOLDER_ISSUER = new X500Principal("CN=localhost, OU=localhost, O=localhost, L=SH, ST=SH, C=CN"); - /** * 获取服务器信息 * - * @return + * @return {@link LicenseExtraModel } */ public LicenseExtraModel getServerInfo() { - LicenseExtraModel serverInfos = ServerInfoUtils.getServerInfos(); - return serverInfos; + return ServerInfoUtils.getServerInfos(); } /** * 生成一个证书 * - * @param paramVO + * @param paramVO param vo + * @throws Exception 例外 */ public void generateLicense(LicenseCreatorParamVO paramVO) throws Exception { - Map map = buildCreator(paramVO); - LicenseCreatorParam param = (LicenseCreatorParam)map.get("creator"); - ZipFile clientZipFile = (ZipFile)map.get("clientZipFile"); + BuildCreatorResp buildCreatorResp = buildCreator(paramVO); + LicenseCreatorParam param = buildCreatorResp.getParam(); + ZipFile clientZipFile = buildCreatorResp.getClientZipFile(); try { LicenseParam licenseParam = initLicenseParam(param); LicenseManager licenseManager = new ServerLicenseManager(licenseParam); - LicenseContent licenseContent = initLcenseContent(param); + LicenseContent licenseContent = initLicenseContent(param); licenseManager.store(licenseContent, new File(param.getLicensePath())); - log.info("{}证书生成成功", param.getSubject()); + log.info("{} 证书生成成功 路径: {}", param.getSubject(), param.getLicensePath()); clientZipFile.addFile(param.getLicensePath()); } catch (Exception e) { - e.printStackTrace(); - // log.error("{}生成证书失败:", param.getSubject()); - throw new LicenseException("生成证书失败:" + param.getSubject()); + throw new LicenseException("生成证书失败:" + param.getSubject(), e); } - } /** - * 封装证书生成参数 + * 构建 License 创建者对象及客户端配置压缩包。 + * + * @param paramVO 创建参数封装对象,包含客户名、密码、描述、扩展信息等。 + * @return Map 包含 LicenseCreatorParam(creator) 和 生成的客户端 Zip 文件(clientZipFile) + * @throws Exception 命令执行或文件操作过程中出现异常 */ - private Map buildCreator(LicenseCreatorParamVO paramVO) throws Exception { + private BuildCreatorResp buildCreator(LicenseCreatorParamVO paramVO) throws Exception { String customerName = paramVO.getCustomerName(); String privateAlias = customerName + "-private-alias"; String publicAlias = customerName + "-public-alias"; - String relativePath = relativePath(paramVO); - String currentCustomerDir = relativePath + customerName + uuid() + File.separator; - File file = new File(currentCustomerDir); - if (!file.exists()) { - file.mkdirs(); + String currentCustomerDir = relativePath(paramVO) + customerName + IdUtil.fastSimpleUUID() + File.separator; + File customerDirFile = new File(currentCustomerDir); + if (!customerDirFile.exists() && !customerDirFile.mkdirs()) { + throw new IOException("Failed to create directory: " + currentCustomerDir); } + String privateKeystore = currentCustomerDir + "privateKeys.keystore"; String publicKeystore = currentCustomerDir + "publicCerts.keystore"; + String certFilePath = currentCustomerDir + "certfile.cer"; + String licensePath = currentCustomerDir + "license.lic"; LicenseCreatorParam param = new LicenseCreatorParam(); param.setSubject(customerName); param.setPrivateAlias(privateAlias); param.setKeyPass(paramVO.getKeyPass()); param.setStorePass(paramVO.getStorePass()); - param.setLicensePath(currentCustomerDir + "license.lic"); + param.setLicensePath(licensePath); param.setPrivateKeysStorePath(privateKeystore); param.setExpiryTime(paramVO.getExpireTime()); param.setDescription(paramVO.getDescription()); param.setLicenseExtraModel(paramVO.getLicenseExtraModel()); - if (checkJavaVersion()) { - // JDK>=17 生成私钥库 + int validity = getValidity(param.getIssuedTime(), paramVO.getExpireTime()); + String dname = "\"CN=localhost, OU=localhost, O=localhost, L=SH, ST=SH, C=CN\""; - String exe1 = "keytool -genkeypair -keyalg DSA -keysize 1024 -validity " + getValidity(param - .getIssuedTime(), paramVO - .getExpireTime()) + " -alias " + privateAlias + " -keystore " + privateKeystore + " -storepass " + paramVO - .getStorePass() + " -keypass " + paramVO - .getKeyPass() + " -dname \"CN=localhost, OU=localhost, O=localhost, L=SH, ST=SH, C=CN\""; - String exe2 = "keytool -exportcert -alias " + privateAlias + " -keystore " + privateKeystore + " -storepass " + paramVO - .getStorePass() + " -file \"" + currentCustomerDir + "certfile.cer\""; + // 生成私钥库 + String keyAlgOption = checkJavaVersion() ? "-keyalg DSA" : ""; // JDK>=17 要指定 keyalg + String genKeyCmd = String + .format("keytool -genkeypair %s -keysize 1024 -validity %d -alias %s -keystore %s -storepass %s -keypass %s -dname %s", keyAlgOption, validity, privateAlias, privateKeystore, paramVO + .getStorePass(), paramVO.getKeyPass(), dname); - String exe3 = "keytool -noprompt -import -alias " + publicAlias + " -file \"" + currentCustomerDir + "certfile.cer\"" + " -keystore " + publicKeystore + " -storepass " + paramVO - .getStorePass(); + // 导出证书 + String exportCertCmd = String + .format("keytool -exportcert -alias %s -keystore %s -storepass %s -file \"%s\"", privateAlias, privateKeystore, paramVO + .getStorePass(), certFilePath); - ExecCmdUtil.exec(exe1); - ExecCmdUtil.exec(exe2); - ExecCmdUtil.exec(exe3); + // 导入到公钥库 + String importCertCmd = String + .format("keytool -noprompt -import -alias %s -file \"%s\" -keystore %s -storepass %s", publicAlias, certFilePath, publicKeystore, paramVO + .getStorePass()); - } else { - // JDK<17 生成私钥库 - String exe1 = "keytool -genkeypair -keysize 1024 -validity " + getValidity(param.getIssuedTime(), paramVO - .getExpireTime()) + " -alias " + privateAlias + " -keystore " + privateKeystore + " -storepass " + paramVO - .getStorePass() + " -keypass " + paramVO - .getKeyPass() + " -dname \"CN=localhost, OU=localhost, " + "O=localhost, L=SH, ST=SH, C=CN\""; - String exe2 = "keytool -exportcert -alias " + privateAlias + " -keystore " + privateKeystore + " -storepass " + paramVO - .getStorePass() + " -file \"" + currentCustomerDir + "certfile.cer\""; - String exe3 = "keytool -noprompt -import -alias " + publicAlias + " -file \"" + currentCustomerDir + "certfile.cer\" -keystore " + publicKeystore + " -storepass " + paramVO - .getStorePass(); - ExecCmdUtil.exec(exe1); - ExecCmdUtil.exec(exe2); - ExecCmdUtil.exec(exe3); - } + // 执行命令 + ExecCmdUtil.exec(genKeyCmd); + ExecCmdUtil.exec(exportCertCmd); + ExecCmdUtil.exec(importCertCmd); + // 生成客户端配置文件 ZipFile clientZipFile = generateClientConfig(param, currentCustomerDir, publicAlias); - Map map = new HashMap<>(); - map.put("creator", param); - map.put("clientZipFile", clientZipFile); - return map; - } - - private String uuid() { - return UUID.randomUUID().toString().replace("-", ""); + return new BuildCreatorResp(param, clientZipFile); } /** * 校验JDK版本 * - * @return - * @throws Exception + * @return boole T 17 版本 F 非 17 版本 + * @throws Exception 例外 */ private boolean checkJavaVersion() throws Exception { String version = System.getProperty("java.version"); - int currentVersion = 0; if (version.startsWith("1.")) { currentVersion = Integer.parseInt(version.split("\\.")[1]); } else { currentVersion = Integer.parseInt(version.split("\\.")[0]); } - - if (currentVersion >= 17) { - return true; - } else { - return false; - } + return currentVersion >= 17; } private ZipFile generateClientConfig(LicenseCreatorParam param, @@ -229,17 +198,16 @@ public class LicenseCreateService { FileOutputStream out = null; try { out = new FileOutputStream(config); - out.write(json.getBytes("UTF-8")); + out.write(json.getBytes(StandardCharsets.UTF_8)); out.flush(); } catch (Exception e) { - e.printStackTrace(); - throw new LicenseException("密钥文件生成失败"); + throw new LicenseException("密钥文件生成失败", e); } finally { if (out != null) { try { out.close(); } catch (IOException e) { - e.printStackTrace(); + throw new LicenseException("文件流关闭失败", e); } } } @@ -250,28 +218,41 @@ public class LicenseCreateService { return clientLicense; } - //将有效时间转换成天 + /** + * 将有效时间转换成天 + * + * @param issuedTime 签发时间 + * @param expireTime 过期时间 + * @return int + */ private int getValidity(Date issuedTime, Date expireTime) { long issued = issuedTime.getTime(); long expire = expireTime.getTime(); long differ = expire - issued; long remaining = differ % (24L * 3600L * 1000L); - Long validity = differ / (24L * 3600L * 1000L); + long validity = differ / (24L * 3600L * 1000L); if (remaining > 0) { validity++; } - return validity.intValue(); + return (int)validity; } + /** + * 是否是 Windows + * + * @return boolean + */ private boolean isWindows() { String os = System.getProperty("os.name"); - if (os.toLowerCase().contains("windows")) { - return true; - } - return false; + return os.toLowerCase().contains("windows"); } - //证书生成路径 + /** + * 证书生成路径 + * + * @param paramVO param vo + * @return {@link String } + */ private String relativePath(LicenseCreatorParamVO paramVO) { if (paramVO.getLicenseSavePath() != null) { @@ -292,16 +273,17 @@ public class LicenseCreateService { CipherParam cipherParam = new DefaultCipherParam(param.getStorePass()); KeyStoreParam privateStoreParam = new CustomKeyStoreParam(LicenseCreateService.class, param .getPrivateKeysStorePath(), param.getPrivateAlias(), param.getStorePass(), param.getKeyPass()); - LicenseParam licenseParam = new DefaultLicenseParam(param - .getSubject(), preferences, privateStoreParam, cipherParam); - return licenseParam; + return new DefaultLicenseParam(param.getSubject(), preferences, privateStoreParam, cipherParam); } /** * 设置证书生成内容 + * + * @param param 参数 + * @return {@link LicenseContent } */ - private LicenseContent initLcenseContent(LicenseCreatorParam param) { + private LicenseContent initLicenseContent(LicenseCreatorParam param) { LicenseContent licenseContent = new LicenseContent(); licenseContent.setHolder(DEFAULT_HOLDER_ISSUER); @@ -314,7 +296,7 @@ public class LicenseCreateService { licenseContent.setConsumerAmount(param.getConsumerAmount()); licenseContent.setInfo(param.getDescription()); - if (param != null && param.getLicenseExtraModel() != null) { + if (param.getLicenseExtraModel() != null) { licenseContent.setExtra(param.getLicenseExtraModel()); } diff --git a/continew-starter-license/continew-starter-license-verify/pom.xml b/continew-starter-license/continew-starter-license-verify/pom.xml index d8df226a..08a6abde 100644 --- a/continew-starter-license/continew-starter-license-verify/pom.xml +++ b/continew-starter-license/continew-starter-license-verify/pom.xml @@ -11,25 +11,14 @@ continew-starter-license-verify jar - license 校验模块 基于 truelicens 实现 + ContiNew Starter License校验模块 - + top.continew - continew-starter-log-core + continew-starter-license-core - - - de.schlichtherle.truelicense - truelicense-core - - - - - net.lingala.zip4j - zip4j - \ No newline at end of file diff --git a/continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/Initializing/LicenseStarterInitializingBean.java b/continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/Initializing/LicenseStarterInitializingBean.java index 159bc6d7..fe808fe2 100644 --- a/continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/Initializing/LicenseStarterInitializingBean.java +++ b/continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/Initializing/LicenseStarterInitializingBean.java @@ -17,7 +17,6 @@ package top.continew.license.Initializing; import org.springframework.beans.factory.InitializingBean; - import top.continew.license.bean.LicenseInstallerBean; /** @@ -34,8 +33,7 @@ public class LicenseStarterInitializingBean implements InitializingBean { } @Override - public void afterPropertiesSet() throws Exception { - // 安装证书,即校验客户机器参数是否符合证书要求,符合则安装成功,不符合则报错无法启动。 + public void afterPropertiesSet() { licenseInstallerBean.installLicense(); } } diff --git a/continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/autoconfigure/LicenseVerifyAutoConfiguration.java b/continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/autoconfigure/LicenseVerifyAutoConfiguration.java index e74e955f..b105b268 100644 --- a/continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/autoconfigure/LicenseVerifyAutoConfiguration.java +++ b/continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/autoconfigure/LicenseVerifyAutoConfiguration.java @@ -35,7 +35,7 @@ import top.continew.starter.core.constant.PropertiesConstants; * license 校验模块 自动配置 * * @author loach - * @since 1.2.0 + * @since 2.11.0 */ @AutoConfiguration @EnableConfigurationProperties(LicenseVerifyProperties.class) @@ -44,7 +44,12 @@ public class LicenseVerifyAutoConfiguration { private static final Logger log = LoggerFactory.getLogger(LicenseVerifyAutoConfiguration.class); - /** 证书安装业务类 */ + /** + * 证书安装业务类 + * + * @param properties 属性 + * @return {@link LicenseInstallerBean } + */ @Bean public LicenseInstallerBean licenseInstallerBean(LicenseVerifyProperties properties) { return new LicenseInstallerBean(properties); @@ -52,6 +57,9 @@ public class LicenseVerifyAutoConfiguration { /** * 启动校验 License服务 + * + * @param licenseInstallerBean 许可证安装程序bean + * @return {@link LicenseStarterInitializingBean } */ @Bean @DependsOn("licenseInstallerBean") @@ -59,7 +67,12 @@ public class LicenseVerifyAutoConfiguration { return new LicenseStarterInitializingBean(licenseInstallerBean); } - /** 客户端证书管理类(证书验证) */ + /** + * 客户端证书管理类(证书验证) + * + * @param properties 属性 + * @return {@link LicenseManager } + */ @Bean public LicenseManager licenseManager(LicenseVerifyProperties properties) { return CustomLicenseManager.getInstance(properties); diff --git a/continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/autoconfigure/LicenseVerifyProperties.java b/continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/autoconfigure/LicenseVerifyProperties.java index 1e574170..daed0294 100644 --- a/continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/autoconfigure/LicenseVerifyProperties.java +++ b/continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/autoconfigure/LicenseVerifyProperties.java @@ -25,8 +25,8 @@ import top.continew.starter.core.constant.PropertiesConstants; * license 校验模块配置属性 * * @author loach - * @since 1.2.0 - */ + * @since 2.11.0 + **/ @ConfigurationProperties(PropertiesConstants.LICENSE_VERIFY) public class LicenseVerifyProperties { diff --git a/continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/bean/LicenseInstallerBean.java b/continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/bean/LicenseInstallerBean.java index 2f81a674..5af75d9c 100644 --- a/continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/bean/LicenseInstallerBean.java +++ b/continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/bean/LicenseInstallerBean.java @@ -16,14 +16,16 @@ package top.continew.license.bean; -import de.schlichtherle.license.*; +import de.schlichtherle.license.LicenseContent; +import de.schlichtherle.license.LicenseManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import top.continew.license.autoconfigure.LicenseVerifyProperties; -import top.continew.license.exception.VerifyException; +import top.continew.license.exception.LicenseException; import top.continew.license.manager.CustomLicenseManager; -import java.io.*; +import java.io.File; +import java.nio.file.Paths; /** * 证书安装业务类 @@ -35,44 +37,56 @@ public class LicenseInstallerBean { private static final Logger log = LoggerFactory.getLogger(LicenseInstallerBean.class); + private final LicenseVerifyProperties properties; private LicenseManager licenseManager; - private LicenseVerifyProperties properties; - public LicenseInstallerBean(LicenseVerifyProperties properties) { this.properties = properties; } - // 安装证书 - public void installLicense() throws Exception { + /** + * 安装许可证 + */ + public void installLicense() { try { - licenseManager = CustomLicenseManager.getInstance(properties); + this.licenseManager = CustomLicenseManager.getInstance(properties); licenseManager.uninstall(); - LicenseContent licenseContent = licenseManager.install(new File(properties - .getStorePath() + File.separator + "clientLicense/license.lic")); - log.info("证书认证通过,安装成功"); + File licenseFile = Paths.get(properties.getStorePath(), "clientLicense", "license.lic").toFile(); + LicenseContent licenseContent = licenseManager.install(licenseFile); + log.info("证书认证通过,安装成功: {}", licenseContent.getSubject()); } catch (Exception e) { - e.printStackTrace(); - throw new VerifyException("证书认证失败:" + e + " " + e.getMessage()); - } - - } - - //卸载证书 - public void uninstallLicense() throws Exception { - if (licenseManager != null) { - licenseManager.uninstall(); - //Log.info("证书已卸载"); + throw new LicenseException("证书认证失败", e); } } - //即时验证证书合法性 - public void verify() throws Exception { + /** + * 卸载许可证 + */ + public void uninstallLicense() { if (licenseManager != null) { - licenseManager.verify(); - //Log.info("证书认证通过"); + try { + licenseManager.uninstall(); + log.info("证书已卸载"); + } catch (Exception e) { + log.warn("卸载证书失败", e); + } + } + } + + /** + * 即时验证证书合法性 + */ + public void verify() { + if (licenseManager != null) { + try { + licenseManager.verify(); + log.info("证书验证成功"); + } catch (Exception e) { + throw new LicenseException("证书认证失败", e); + } + } else { + throw new LicenseException("证书认证失败: licenseManager is null"); } - throw new VerifyException("证书认证失败:licenseManager is null"); } } diff --git a/continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/dto/LicenseExtraModel.java b/continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/dto/LicenseExtraModel.java deleted file mode 100644 index 63cfcce3..00000000 --- a/continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/dto/LicenseExtraModel.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. - *

- * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

- * http://www.gnu.org/licenses/lgpl.html - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package top.continew.license.dto; - -import java.util.Set; - -/** - * 额外的服务器硬件校验信息对象,这里的属性可根据需求自定义 - * - * @Desc: - * @Author loach - * @ClassName top.continew.license.dto.LicenseExtraModel - * @Date 2025-03-21 14:28 - */ -public class LicenseExtraModel { - - /** - * 可被允许的IP地址 - */ - private Set ipAddress; - - /** - * 可被允许的mac地址 - */ - private Set macAddress; - - /** - * 可被允许的CPU序列号 - */ - private String cpuSerial; - - /** - * 可被允许的主板序列号 - */ - private String mainBoardSerial; - - public Set getIpAddress() { - return ipAddress; - } - - public void setIpAddress(Set ipAddress) { - this.ipAddress = ipAddress; - } - - public Set getMacAddress() { - return macAddress; - } - - public void setMacAddress(Set macAddress) { - this.macAddress = macAddress; - } - - public String getCpuSerial() { - return cpuSerial; - } - - public void setCpuSerial(String cpuSerial) { - this.cpuSerial = cpuSerial; - } - - public String getMainBoardSerial() { - return mainBoardSerial; - } - - public void setMainBoardSerial(String mainBoardSerial) { - this.mainBoardSerial = mainBoardSerial; - } - -} diff --git a/continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/exception/VerifyException.java b/continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/exception/VerifyException.java deleted file mode 100644 index e0068672..00000000 --- a/continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/exception/VerifyException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. - *

- * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

- * http://www.gnu.org/licenses/lgpl.html - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package top.continew.license.exception; - -/** - * 自定义校验异常 - * - * @Desc: - * @Author loach - * @ClassName top.continew.license.exception.VerifyException - * @Date 2025-04-11 14:58 - */ -public class VerifyException extends RuntimeException { - public VerifyException(String message) { - super(message); - } - -} diff --git a/continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/manager/CustomLicenseManager.java b/continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/manager/CustomLicenseManager.java index e3905e7a..2ae67ba9 100644 --- a/continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/manager/CustomLicenseManager.java +++ b/continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/manager/CustomLicenseManager.java @@ -20,27 +20,30 @@ import com.fasterxml.jackson.databind.ObjectMapper; import de.schlichtherle.license.*; import de.schlichtherle.xml.GenericCertificate; import net.lingala.zip4j.ZipFile; -import net.lingala.zip4j.exception.ZipException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; -import top.continew.license.bean.LicenseInstallerBean; import top.continew.license.autoconfigure.LicenseVerifyProperties; -import top.continew.license.dto.ConfigParam; -import top.continew.license.dto.LicenseExtraModel; -import top.continew.license.keyStoreParam.CustomKeyStoreParam; -import top.continew.license.utils.ServerInfoUtils; +import top.continew.license.bean.LicenseInstallerBean; +import top.continew.license.exception.LicenseException; +import top.continew.license.model.ConfigParam; +import top.continew.license.model.CustomKeyStoreParam; +import top.continew.license.model.LicenseExtraModel; +import top.continew.license.util.ServerInfoUtils; -import java.io.*; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.prefs.Preferences; /** * 客户端证书管理类(证书验证) * * @author loach - * @since 1.2.0 + * @since 2.11.0 */ -@Component public class CustomLicenseManager extends LicenseManager { private static final Logger log = LoggerFactory.getLogger(CustomLicenseManager.class); @@ -48,7 +51,7 @@ public class CustomLicenseManager extends LicenseManager { private static volatile CustomLicenseManager INSTANCE; private LicenseExtraModel extraModel; - private LicenseVerifyProperties properties; + private final LicenseVerifyProperties properties; private CustomLicenseManager(LicenseVerifyProperties properties) { this.properties = properties; @@ -87,67 +90,49 @@ public class CustomLicenseManager extends LicenseManager { /** * 解压压缩包 - * - * @throws ZipException */ private void extractZip() { - ZipFile config = new ZipFile(properties.getStorePath() + File.separator + "clientLicense.zip"); - File licenseDir = new File(properties.getStorePath() + File.separator + "clientLicense"); - if (!licenseDir.exists()) { - licenseDir.mkdir(); - } - try { - config.extractAll(licenseDir.getAbsolutePath()); - } catch (ZipException e) { - log.error(e.getMessage()); - throw new RuntimeException(e); + Path zipPath = Paths.get(properties.getStorePath(), "clientLicense.zip"); + Path outputDir = Paths.get(properties.getStorePath(), "clientLicense"); + + try (ZipFile zipFile = new ZipFile(zipPath.toFile())) { + if (!Files.exists(outputDir)) { + Files.createDirectories(outputDir); + } + zipFile.extractAll(outputDir.toAbsolutePath().toString()); + } catch (IOException e) { + log.error("解压 clientLicense.zip 出错: {}", e.getMessage(), e); + throw new LicenseException("解压失败", e); } } /** * 获取压缩文件中配置的基础参数 * - * @return - * @throws Exception + * @return {@link ConfigParam } */ private ConfigParam getConfigParam() { - FileInputStream config = null; - BufferedReader reader = null; - try { - config = new FileInputStream(properties - .getStorePath() + File.separator + "clientLicense/clientConfig.json"); - reader = new BufferedReader(new InputStreamReader(config, "UTF-8")); - StringBuilder sb = new StringBuilder(); - String temp = null; - while ((temp = reader.readLine()) != null) { - sb.append(temp); - } - ObjectMapper mapper = new ObjectMapper(); - ConfigParam configParam = mapper.readValue(sb.toString(), ConfigParam.class); - return configParam; - } catch (IOException e) { - e.printStackTrace(); - } finally { - if (reader != null) { - try { - reader.close(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - if (config != null) { - try { - config.close(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } + Path configPath = Paths.get(properties.getStorePath(), "clientLicense", "clientConfig.json"); + + if (!Files.exists(configPath)) { + log.warn("配置文件不存在: {}", configPath); + return null; + } + + try (InputStream inputStream = Files.newInputStream(configPath)) { + ObjectMapper mapper = new ObjectMapper(); + return mapper.readValue(inputStream, ConfigParam.class); + } catch (IOException e) { + log.error("读取配置文件失败: {}", e.getMessage(), e); + return null; } - return null; } /** * 重写验证证书方法,添加自定义参数验证 + * + * @param content 内容 + * @throws LicenseContentException 许可证内容例外 */ @Override protected synchronized void validate(LicenseContent content) throws LicenseContentException { @@ -155,27 +140,31 @@ public class CustomLicenseManager extends LicenseManager { super.validate(content); // 验证自定义参数 Object o = content.getExtra(); - if (o != null && extraModel != null && o instanceof LicenseExtraModel) { - LicenseExtraModel contentExtraModel = (LicenseExtraModel)o; + if (extraModel != null && o instanceof LicenseExtraModel contentExtraModel) { if (!contentExtraModel.getCpuSerial().equals(extraModel.getCpuSerial())) { - throw new LicenseContentException("CPU核数不匹配"); + throw new LicenseException("CPU核数不匹配"); } if (!contentExtraModel.getMainBoardSerial().equals(extraModel.getMainBoardSerial())) { - throw new LicenseContentException("主板序列号不匹配"); + throw new LicenseException("主板序列号不匹配"); } if (!contentExtraModel.getIpAddress().equals(extraModel.getIpAddress())) { - throw new LicenseContentException("IP地址不匹配"); + throw new LicenseException("IP地址不匹配"); } if (!contentExtraModel.getMacAddress().equals(extraModel.getMacAddress())) { - throw new LicenseContentException("MAC地址不匹配"); + throw new LicenseException("MAC地址不匹配"); } } else { - throw new LicenseContentException("证书无效"); + throw new LicenseException("证书无效"); } } /** * 重写证书安装方法,主要是更改调用本类的验证方法 + * + * @param key 钥匙 + * @param notary 公证人 + * @return {@link LicenseContent } + * @throws Exception 例外 */ @Override protected synchronized LicenseContent install(final byte[] key, LicenseNotary notary) throws Exception { @@ -192,23 +181,31 @@ public class CustomLicenseManager extends LicenseManager { /** * 重写验证证书合法的方法,主要是更改调用本类的验证方法 + * + * @param notary 公证人 + * @return {@link LicenseContent } + * @throws Exception 例外 */ @Override protected synchronized LicenseContent verify(LicenseNotary notary) throws Exception { GenericCertificate certificate = getCertificate(); - if (null != certificate) + if (certificate != null) { return (LicenseContent)certificate.getContent(); - - // Load license key from preferences, - final byte[] key = getLicenseKey(); - if (null == key) - throw new NoLicenseInstalledException(getLicenseParam().getSubject()); - certificate = getPrivacyGuard().key2cert(key); + } + byte[] licenseKey = getLicenseKey(); + if (licenseKey == null) { + String subject = getLicenseParam().getSubject(); + throw new NoLicenseInstalledException(subject); + } + // 使用私钥解密生成证书 + certificate = getPrivacyGuard().key2cert(licenseKey); + // 验证证书签名 notary.verify(certificate); - final LicenseContent content = (LicenseContent)certificate.getContent(); + // 提取内容并进行业务校验 + LicenseContent content = (LicenseContent)certificate.getContent(); this.validate(content); + // 缓存证书 setCertificate(certificate); - return content; } } diff --git a/continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/utils/ServerInfoUtils.java b/continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/utils/ServerInfoUtils.java deleted file mode 100644 index 7d499fe4..00000000 --- a/continew-starter-license/continew-starter-license-verify/src/main/java/top/continew/license/utils/ServerInfoUtils.java +++ /dev/null @@ -1,338 +0,0 @@ -/* - * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. - *

- * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

- * http://www.gnu.org/licenses/lgpl.html - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package top.continew.license.utils; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.collection.CollectionUtil; -import cn.hutool.core.io.FileUtil; -import cn.hutool.core.io.IoUtil; -import cn.hutool.core.util.StrUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import top.continew.license.dto.LicenseExtraModel; -import top.continew.license.exception.VerifyException; - -import java.io.*; -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.net.SocketException; -import java.util.Collections; -import java.util.Enumeration; -import java.util.Set; -import java.util.stream.Collectors; - -/** - * 服务器信息工具类 - * - * @author Rong.Jia - * @date 2022/03/10 - */ -public class ServerInfoUtils { - - private static final Logger log = LoggerFactory.getLogger(ServerInfoUtils.class); - - private static class ServerInfosContainer { - private static Set ipAddress = null; - private static Set macAddress = null; - private static String cpuSerial = null; - private static String mainBoardSerial = null; - } - - /** - * 组装需要额外校验的License参数 - * - * @return - */ - public static LicenseExtraModel getServerInfos() { - LicenseExtraModel result = new LicenseExtraModel(); - try { - initServerInfos(); - result.setIpAddress(ServerInfosContainer.ipAddress); - result.setMacAddress(ServerInfosContainer.macAddress); - result.setCpuSerial(ServerInfosContainer.cpuSerial); - result.setMainBoardSerial(ServerInfosContainer.mainBoardSerial); - } catch (Exception e) { - log.error("获取服务器硬件信息异常", e); - throw new VerifyException(String.format("获取服务器硬件信息异常, %s", e.getMessage())); - } - return result; - } - - /** - * 初始化服务器硬件信息,并将信息缓存到内存 - * - * @throws Exception 默认异常 - */ - private static void initServerInfos() throws Exception { - if (ServerInfosContainer.ipAddress == null) { - ServerInfosContainer.ipAddress = getIpAddress(); - } - if (ServerInfosContainer.macAddress == null) { - ServerInfosContainer.macAddress = getMacAddress(); - } - if (ServerInfosContainer.cpuSerial == null) { - ServerInfosContainer.cpuSerial = getCpuSerial(); - } - if (ServerInfosContainer.mainBoardSerial == null) { - ServerInfosContainer.mainBoardSerial = getMainBoardSerial(); - } - } - - /** - * 获取服务器临时磁盘位置 - * - * @return {@link String} - */ - public static String getServerTempPath() { - return System.getProperty("user.dir"); - } - - /** - * 获取CPU序列号 - * - * @return String 主板序列号 - */ - public static String getCpuSerial() { - return FileUtil.isWindows() ? getWindowCpuSerial() : getLinuxCpuSerial(); - } - - /** - * 获取主板序列号 - * - * @return String 主板序列号 - */ - public static String getMainBoardSerial() { - return FileUtil.isWindows() ? getWindowMainBoardSerial() : getLinuxMainBoardSerial(); - } - - /** - * 获取linux cpu 序列号 - * - * @return {@link String} - */ - private static String getLinuxCpuSerial() { - String result = StrUtil.EMPTY; - String cpuIdCmd = "dmidecode"; - BufferedReader bufferedReader = null; - try { - // 管道 - Process p = Runtime.getRuntime().exec(new String[] {"sh", "-c", cpuIdCmd}); - bufferedReader = new BufferedReader(new InputStreamReader(p.getInputStream())); - String line = null; - int index = -1; - while ((line = bufferedReader.readLine()) != null) { - // 寻找标示字符串[hwaddr] - index = line.toLowerCase().indexOf("uuid"); - if (index >= 0) { - // 取出mac地址并去除2边空格 - result = line.substring(index + "uuid".length() + 1).trim(); - break; - } - } - } catch (IOException e) { - log.error("获取Linux cpu信息错误 {}", e.getMessage()); - } finally { - IoUtil.close(bufferedReader); - } - return result.trim(); - } - - /** - * 获取Window cpu 序列号 - * - * @return {@link String} - */ - private static String getWindowCpuSerial() { - - String result = StrUtil.EMPTY; - File file = null; - BufferedReader input = null; - try { - file = File.createTempFile("tmp", ".vbs"); - file.deleteOnExit(); - FileWriter fw = new FileWriter(file); - String vbs = "Set objWMIService = GetObject(\"winmgmts:\\\\.\\root\\cimv2\")\n" + "Set colItems = objWMIService.ExecQuery _ \n" + " (\"Select * from Win32_Processor\") \n" + "For Each objItem in colItems \n" + " Wscript.Echo objItem.ProcessorId \n" + " exit for ' do the first cpu only! \n" + "Next \n"; - - fw.write(vbs); - fw.close(); - - Process p = Runtime.getRuntime().exec("cscript //NoLogo " + file.getPath()); - input = new BufferedReader(new InputStreamReader(p.getInputStream())); - String line; - while ((line = input.readLine()) != null) { - result += line; - } - } catch (Exception e) { - log.error("获取window cpu信息错误, {}", e.getMessage()); - } finally { - IoUtil.close(input); - FileUtil.del(file); - } - return result.trim(); - } - - /** - * 获取Linux主板序列号 - * - * @return {@link String} - */ - private static String getLinuxMainBoardSerial() { - String result = StrUtil.EMPTY; - String maniBordCmd = "dmidecode | grep 'Serial Number' | awk '{print $3}' | tail -1"; - BufferedReader br = null; - try { - Process p = Runtime.getRuntime().exec(new String[] {"sh", "-c", maniBordCmd}); - br = new BufferedReader(new InputStreamReader(p.getInputStream())); - String line; - while ((line = br.readLine()) != null) { - result += line; - break; - } - } catch (IOException e) { - log.error("获取Linux主板信息错误 {}", e.getMessage()); - } finally { - IoUtil.close(br); - } - return result; - } - - /** - * 获取window主板序列号 - * - * @return {@link String} - */ - private static String getWindowMainBoardSerial() { - String result = StrUtil.EMPTY; - File file = null; - BufferedReader input = null; - try { - file = File.createTempFile("realhowto", ".vbs"); - file.deleteOnExit(); - FileWriter fw = new FileWriter(file); - - String vbs = "Set objWMIService = GetObject(\"winmgmts:\\\\.\\root\\cimv2\")\n" + "Set colItems = objWMIService.ExecQuery _ \n" + " (\"Select * from Win32_BaseBoard\") \n" + "For Each objItem in colItems \n" + " Wscript.Echo objItem.SerialNumber \n" + " exit for ' do the first cpu only! \n" + "Next \n"; - - fw.write(vbs); - fw.close(); - Process p = Runtime.getRuntime().exec("cscript //NoLogo " + file.getPath()); - input = new BufferedReader(new InputStreamReader(p.getInputStream())); - String line; - while ((line = input.readLine()) != null) { - result += line; - } - } catch (Exception e) { - log.error("获取Window主板信息错误 {}", e.getMessage()); - } finally { - IoUtil.close(input); - FileUtil.del(file); - } - return result.trim(); - } - - /** - *

获取Mac地址

- * - * @return List Mac地址 - * @throws Exception 默认异常 - */ - public static Set getMacAddress() throws Exception { - // 获取所有网络接口 - Set inetAddresses = getLocalAllInetAddress(); - if (CollectionUtil.isNotEmpty(inetAddresses)) { - return inetAddresses.stream() - .map(ServerInfoUtils::getMacByInetAddress) - .distinct() - .collect(Collectors.toSet()); - } - return Collections.emptySet(); - } - - /** - *

获取IP地址

- * - * @return List IP地址 - * @throws Exception 默认异常 - */ - public static Set getIpAddress() throws Exception { - // 获取所有网络接口 - Set inetAddresses = getLocalAllInetAddress(); - if (CollectionUtil.isNotEmpty(inetAddresses)) { - return inetAddresses.stream() - .map(InetAddress::getHostAddress) - .distinct() - .map(String::toLowerCase) - .collect(Collectors.toSet()); - } - return Collections.emptySet(); - } - - /** - *

获取某个网络地址对应的Mac地址

- * - * @param inetAddr 网络地址 - * @return String Mac地址 - */ - private static String getMacByInetAddress(InetAddress inetAddr) { - try { - byte[] mac = NetworkInterface.getByInetAddress(inetAddr).getHardwareAddress(); - StringBuilder stringBuilder = new StringBuilder(); - for (int i = 0; i < mac.length; i++) { - if (i != 0) { - stringBuilder.append("-"); - } - // 将十六进制byte转化为字符串 - String temp = Integer.toHexString(mac[i] & 0xff); - if (temp.length() == 1) { - stringBuilder.append("0").append(temp); - } else { - stringBuilder.append(temp); - } - } - return stringBuilder.toString().toUpperCase(); - } catch (SocketException e) { - log.error("getMacByInetAddress {}", e.getMessage()); - } - return null; - } - - /** - *

获取当前服务器所有符合条件的网络地址

- * - * @return List 网络地址列表 - * @throws Exception 默认异常 - */ - private static Set getLocalAllInetAddress() throws Exception { - - Set result = CollUtil.newHashSet(); - // 遍历所有的网络接口 - for (Enumeration networkInterfaces = NetworkInterface.getNetworkInterfaces(); - networkInterfaces.hasMoreElements();) { - NetworkInterface ni = networkInterfaces.nextElement(); - // 在所有的接口下再遍历IP - for (Enumeration addresses = ni.getInetAddresses(); addresses.hasMoreElements();) { - InetAddress address = addresses.nextElement(); - //排除LoopbackAddress、SiteLocalAddress、LinkLocalAddress、MulticastAddress类型的IP地址 - /*&& !inetAddr.isSiteLocalAddress()*/ - if (!address.isLoopbackAddress() && !address.isLinkLocalAddress() && !address.isMulticastAddress()) { - result.add(address); - } - } - } - return result; - } - -} diff --git a/continew-starter-license/pom.xml b/continew-starter-license/pom.xml index 3c43369c..78454aa7 100644 --- a/continew-starter-license/pom.xml +++ b/continew-starter-license/pom.xml @@ -11,17 +11,10 @@ continew-starter-license pom - ContiNew Starter license 管理模块 + ContiNew Starter License模块 + continew-starter-license-core continew-starter-license-generate continew-starter-license-verify - - - - - top.continew - continew-starter-core - - \ No newline at end of file