diff --git a/detection/src/main/java/com/njcn/gather/activate/config/RSAProperties.java b/detection/src/main/java/com/njcn/gather/activate/config/RSAProperties.java
new file mode 100644
index 00000000..8687467a
--- /dev/null
+++ b/detection/src/main/java/com/njcn/gather/activate/config/RSAProperties.java
@@ -0,0 +1,17 @@
+package com.njcn.gather.activate.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+@Data
+@ConfigurationProperties(prefix = "rsa")
+public class RSAProperties {
+ /**
+ * RSA公钥
+ */
+ private String publicKey;
+ /**
+ * RSA私钥
+ */
+ private String privateKey;
+}
diff --git a/detection/src/main/java/com/njcn/gather/activate/controller/ActivateController.java b/detection/src/main/java/com/njcn/gather/activate/controller/ActivateController.java
new file mode 100644
index 00000000..612483fa
--- /dev/null
+++ b/detection/src/main/java/com/njcn/gather/activate/controller/ActivateController.java
@@ -0,0 +1,74 @@
+package com.njcn.gather.activate.controller;
+
+import cn.hutool.json.JSONUtil;
+import com.njcn.common.pojo.annotation.OperateInfo;
+import com.njcn.common.pojo.enums.common.LogEnum;
+import com.njcn.common.pojo.enums.response.CommonResponseEnum;
+import com.njcn.common.pojo.response.HttpResult;
+import com.njcn.common.utils.LogUtil;
+import com.njcn.gather.activate.pojo.vo.ActivationCodePlaintext;
+import com.njcn.gather.activate.pojo.vo.ApplicationCodePlaintext;
+import com.njcn.gather.activate.service.ActivateService;
+import com.njcn.web.controller.BaseController;
+import com.njcn.web.utils.HttpResultUtil;
+import io.swagger.annotations.*;
+import lombok.Data;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@Slf4j
+@Api(tags = "设备激活管理")
+@RestController
+@RequestMapping("/activate")
+@RequiredArgsConstructor
+public class ActivateController extends BaseController {
+
+ private final ActivateService activateService;
+
+ @OperateInfo(info = LogEnum.BUSINESS_COMMON)
+ @ApiOperation("生成设备申请码")
+ @ApiImplicitParam(name = "data", value = "生成设备申请码参数", required = true)
+ @PostMapping("/generateApplicationCode")
+ public HttpResult generateApplicationCode(@RequestBody ApplicationCodePlaintext data) {
+ String methodDescribe = getMethodDescribe("generateApplicationCode");
+ LogUtil.njcnDebug(log, "{},生成设备申请码:{}", methodDescribe, JSONUtil.toJsonStr(data));
+ String applicationCode = activateService.generateApplicationCode(data);
+ return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, applicationCode, methodDescribe);
+ }
+
+ @OperateInfo(info = LogEnum.BUSINESS_COMMON)
+ @ApiOperation("验证设备激活码")
+ @ApiImplicitParam(name = "params", value = "验证设备激活码参数", required = true)
+ @PostMapping("/verifyActivationCode")
+ public HttpResult verifyActivationCode(@RequestBody VerifyActivationCodeParams params) {
+ String methodDescribe = getMethodDescribe("verifyActivationCode");
+ LogUtil.njcnDebug(log, "{},验证设备激活码\":{}", methodDescribe, JSONUtil.toJsonStr(params));
+ ActivationCodePlaintext activationCodePlaintext = activateService.verifyActivationCode(params.getActivationCode());
+ return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, activationCodePlaintext, methodDescribe);
+ }
+
+ @OperateInfo(info = LogEnum.BUSINESS_COMMON)
+ @ApiOperation("获取许可信息")
+ @PostMapping("/getLicense")
+ public HttpResult getLicense() {
+ String methodDescribe = getMethodDescribe("checkLicense");
+ LogUtil.njcnDebug(log, "{},获取许可信息", methodDescribe);
+ ActivationCodePlaintext activationCodePlaintext = activateService.readLicenseFile();
+ if (activationCodePlaintext == null) {
+ activationCodePlaintext = new ActivationCodePlaintext();
+ activationCodePlaintext.init();
+ }
+ return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, activationCodePlaintext, methodDescribe);
+ }
+
+ @ApiModel("验证设备激活码参数")
+ @Data
+ public static class VerifyActivationCodeParams {
+ @ApiModelProperty(value = "激活码")
+ private String activationCode;
+ }
+}
diff --git a/detection/src/main/java/com/njcn/gather/activate/pojo/vo/ActivationCodePlaintext.java b/detection/src/main/java/com/njcn/gather/activate/pojo/vo/ActivationCodePlaintext.java
new file mode 100644
index 00000000..388be796
--- /dev/null
+++ b/detection/src/main/java/com/njcn/gather/activate/pojo/vo/ActivationCodePlaintext.java
@@ -0,0 +1,35 @@
+package com.njcn.gather.activate.pojo.vo;
+
+import lombok.Data;
+
+@Data
+public class ActivationCodePlaintext {
+ /**
+ * mac地址
+ */
+ private String macAddress;
+
+ /**
+ * 模拟式模块
+ */
+ private ActivationModule simulate;
+
+ /**
+ * 数字式模块
+ */
+ private ActivationModule digital;
+
+ /**
+ * 比对式模块
+ */
+ private ActivationModule contrast;
+
+
+ public void init() {
+ simulate = new ActivationModule();
+ digital = new ActivationModule();
+ contrast = new ActivationModule();
+ }
+
+
+}
diff --git a/detection/src/main/java/com/njcn/gather/activate/pojo/vo/ActivationModule.java b/detection/src/main/java/com/njcn/gather/activate/pojo/vo/ActivationModule.java
new file mode 100644
index 00000000..4b82d2aa
--- /dev/null
+++ b/detection/src/main/java/com/njcn/gather/activate/pojo/vo/ActivationModule.java
@@ -0,0 +1,20 @@
+package com.njcn.gather.activate.pojo.vo;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class ActivationModule extends ApplicationModule {
+
+ /**
+ * 是否永久授权
+ */
+ private int permanently;
+
+ public boolean isPermanently() {
+ return permanently == 1;
+ }
+
+
+}
\ No newline at end of file
diff --git a/detection/src/main/java/com/njcn/gather/activate/pojo/vo/ApplicationCodePlaintext.java b/detection/src/main/java/com/njcn/gather/activate/pojo/vo/ApplicationCodePlaintext.java
new file mode 100644
index 00000000..aa06d18b
--- /dev/null
+++ b/detection/src/main/java/com/njcn/gather/activate/pojo/vo/ApplicationCodePlaintext.java
@@ -0,0 +1,35 @@
+package com.njcn.gather.activate.pojo.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@ApiModel("申请码明文")
+@Data
+public class ApplicationCodePlaintext {
+ /**
+ * mac地址
+ */
+ @ApiModelProperty(value = "mac地址", hidden = true)
+ private String macAddress;
+
+ /**
+ * 模拟式模块
+ */
+ @ApiModelProperty("模拟式模块")
+ private ApplicationModule simulate;
+
+ /**
+ * 数字式模块
+ */
+ @ApiModelProperty("数字式模块")
+ private ApplicationModule digital;
+
+ /**
+ * 比对式模块
+ */
+ @ApiModelProperty("比对式模块")
+ private ApplicationModule contrast;
+
+
+}
diff --git a/detection/src/main/java/com/njcn/gather/activate/pojo/vo/ApplicationModule.java b/detection/src/main/java/com/njcn/gather/activate/pojo/vo/ApplicationModule.java
new file mode 100644
index 00000000..eea0e1b2
--- /dev/null
+++ b/detection/src/main/java/com/njcn/gather/activate/pojo/vo/ApplicationModule.java
@@ -0,0 +1,17 @@
+package com.njcn.gather.activate.pojo.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+public class ApplicationModule {
+ /**
+ * 是否申请 1是 0否
+ */
+ @ApiModelProperty(value = "是否申请 1是 0否")
+ private int apply;
+
+ public boolean isApply() {
+ return apply == 1;
+ }
+}
\ No newline at end of file
diff --git a/detection/src/main/java/com/njcn/gather/activate/service/ActivateService.java b/detection/src/main/java/com/njcn/gather/activate/service/ActivateService.java
new file mode 100644
index 00000000..5665e8a9
--- /dev/null
+++ b/detection/src/main/java/com/njcn/gather/activate/service/ActivateService.java
@@ -0,0 +1,30 @@
+package com.njcn.gather.activate.service;
+
+import com.njcn.gather.activate.pojo.vo.ActivationCodePlaintext;
+import com.njcn.gather.activate.pojo.vo.ApplicationCodePlaintext;
+
+public interface ActivateService {
+
+ /**
+ * 生成设备申请码
+ *
+ * @param data
+ * @return
+ */
+ String generateApplicationCode(ApplicationCodePlaintext data);
+
+ /**
+ * 验证激活码
+ *
+ * @param activationCode
+ * @return
+ */
+ ActivationCodePlaintext verifyActivationCode(String activationCode);
+
+ /**
+ * 读取授权文件
+ *
+ * @return
+ */
+ ActivationCodePlaintext readLicenseFile();
+}
diff --git a/detection/src/main/java/com/njcn/gather/activate/service/impl/ActivateServiceImpl.java b/detection/src/main/java/com/njcn/gather/activate/service/impl/ActivateServiceImpl.java
new file mode 100644
index 00000000..80191b0d
--- /dev/null
+++ b/detection/src/main/java/com/njcn/gather/activate/service/impl/ActivateServiceImpl.java
@@ -0,0 +1,134 @@
+package com.njcn.gather.activate.service.impl;
+
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.net.NetUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.json.JSONUtil;
+import com.njcn.common.pojo.enums.response.CommonResponseEnum;
+import com.njcn.common.pojo.exception.BusinessException;
+import com.njcn.common.utils.RSAUtil;
+import com.njcn.gather.activate.config.RSAProperties;
+import com.njcn.gather.activate.pojo.vo.ActivationCodePlaintext;
+import com.njcn.gather.activate.pojo.vo.ActivationModule;
+import com.njcn.gather.activate.pojo.vo.ApplicationCodePlaintext;
+import com.njcn.gather.activate.service.ActivateService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.stereotype.Service;
+
+import java.io.File;
+
+@RequiredArgsConstructor
+@Slf4j
+@Service
+@EnableConfigurationProperties(RSAProperties.class)
+public class ActivateServiceImpl implements ActivateService {
+ private final RSAProperties rsaProperties;
+ static final String LICENSE_FILE_NAME = "license.key";
+ static final String LICENSE_FILE_PATH = ActivateServiceImpl.class.getProtectionDomain().getCodeSource().getLocation().getPath() + File.separator + LICENSE_FILE_NAME;
+
+ @Override
+ public String generateApplicationCode(ApplicationCodePlaintext data) {
+ // 获取当前设备MAC地址
+ String macAddress = NetUtil.getLocalMacAddress();
+ log.debug("当前设备MAC地址:{}", macAddress);
+ data.setMacAddress(macAddress);
+ String plaintext = JSONUtil.toJsonStr(data);
+ // RSA 加密
+ try {
+ return RSAUtil.encrypt(plaintext, RSAUtil.stringToPublicKey(rsaProperties.getPublicKey()));
+ } catch (Exception e) {
+ log.error("申请码加密失败", e);
+ throw new BusinessException(CommonResponseEnum.FAIL, "申请码生成失败");
+ }
+ }
+
+ @Override
+ public ActivationCodePlaintext verifyActivationCode(String activationCode) {
+ String plaintext;
+ try {
+ plaintext = RSAUtil.decrypt(activationCode, RSAUtil.stringToPrivateKey(rsaProperties.getPrivateKey()));
+ } catch (Exception e) {
+ log.error("授权码解密失败", e);
+ throw new BusinessException(CommonResponseEnum.FAIL, "无效的激活码");
+ }
+ log.info("新授权码解密:{}", JSONUtil.toJsonStr(plaintext));
+ ActivationCodePlaintext activationCodePlaintext = JSONUtil.toBean(plaintext, ActivationCodePlaintext.class);
+ String macAddress = NetUtil.getLocalMacAddress();
+ if (!StrUtil.equals(activationCodePlaintext.getMacAddress(), macAddress)) {
+ log.error("mac地址不匹配");
+ throw new BusinessException(CommonResponseEnum.FAIL, "无效的激活码");
+ }
+ return addOrUpdateLicenseFile(activationCodePlaintext, activationCode);
+ }
+
+ @Override
+ public ActivationCodePlaintext readLicenseFile() {
+ if (FileUtil.exist(LICENSE_FILE_PATH)) {
+ String content = FileUtil.readUtf8String(LICENSE_FILE_PATH);
+ String plaintext;
+ try {
+ plaintext = RSAUtil.decrypt(content, RSAUtil.stringToPrivateKey(rsaProperties.getPrivateKey()));
+ } catch (Exception e) {
+ log.error("授权文件内容解密失败", e);
+ throw new BusinessException(CommonResponseEnum.FAIL, "许可信息读取失败");
+ }
+ return JSONUtil.toBean(plaintext, ActivationCodePlaintext.class);
+ }
+ return null;
+ }
+
+ private ActivationCodePlaintext addOrUpdateLicenseFile(ActivationCodePlaintext newActivationCodePlaintext, String activationCode) {
+ log.info("新授权码明文:{}", JSONUtil.toJsonStr(newActivationCodePlaintext));
+ ActivationModule newContrast = newActivationCodePlaintext.getContrast();
+ ActivationModule newDigital = newActivationCodePlaintext.getDigital();
+ ActivationModule newSimulate = newActivationCodePlaintext.getSimulate();
+ boolean verifyStatus = false;
+ if (newContrast.isApply() && newContrast.isPermanently()) {
+ verifyStatus = true;
+ }
+ if (newDigital.isApply() && newDigital.isPermanently()) {
+ verifyStatus = true;
+ }
+ if (newSimulate.isApply() && newSimulate.isPermanently()) {
+ verifyStatus = true;
+ }
+ if (!verifyStatus) {
+ log.error("授权码格式错误");
+ throw new BusinessException(CommonResponseEnum.FAIL, "无效的激活码");
+ }
+ log.info("授权文件路径:{}", LICENSE_FILE_PATH);
+ ActivationCodePlaintext oldActivationCodePlaintext = this.readLicenseFile();
+ if (oldActivationCodePlaintext == null) {
+ // 如果文件不存在,创建新文件
+ FileUtil.touch(LICENSE_FILE_PATH);
+ // 写入授权文件
+ FileUtil.writeUtf8String(activationCode, LICENSE_FILE_PATH);
+ return newActivationCodePlaintext;
+ } else {
+ log.info("旧授权码明文:{}", JSONUtil.toJsonStr(oldActivationCodePlaintext));
+ if (newContrast.isApply()) {
+ oldActivationCodePlaintext.setContrast(newContrast);
+ }
+ if (newDigital.isApply()) {
+ oldActivationCodePlaintext.setDigital(newDigital);
+ }
+ if (newSimulate.isApply()) {
+ oldActivationCodePlaintext.setSimulate(newSimulate);
+ }
+ log.info("最新授权码明文:{}", JSONUtil.toJsonStr(oldActivationCodePlaintext));
+ String updateContent;
+ // 重新加密
+ try {
+ updateContent = RSAUtil.encrypt(JSONUtil.toJsonStr(oldActivationCodePlaintext), RSAUtil.stringToPublicKey(rsaProperties.getPublicKey()));
+ } catch (Exception e) {
+ log.error("授权文件内容加密失败", e);
+ throw new BusinessException(CommonResponseEnum.FAIL, "激活失败,请联系管理员");
+ }
+ FileUtil.writeUtf8String(updateContent, LICENSE_FILE_PATH);
+ return oldActivationCodePlaintext;
+ }
+ }
+
+}
diff --git a/entrance/src/main/resources/application.yml b/entrance/src/main/resources/application.yml
index ccb3f829..591765ad 100644
--- a/entrance/src/main/resources/application.yml
+++ b/entrance/src/main/resources/application.yml
@@ -6,12 +6,12 @@ spring:
datasource:
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
-# url: jdbc:mysql://192.168.1.24:13306/pqs9100?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
-# username: root
-# password: njcnpqs
- url: jdbc:mysql://localhost:13306/pqs9100member?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
+ url: jdbc:mysql://192.168.1.24:13306/pqs9100_client1?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
username: root
password: njcnpqs
+ # url: jdbc:mysql://localhost:3306/pqs91001?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=CTT
+ # username: root
+ # password: root
#初始化建立物理连接的个数、最小、最大连接数
initial-size: 5
min-idle: 5
@@ -118,3 +118,7 @@ power-quality:
harmonic-times: 50 # 谐波次数
ib-add: false # 电流基波叠加标志
uharm-add: false # 电压谐波叠加标志
+# rsa公私钥
+rsa:
+ private-key: "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCcUyYhVqczGxblL+o/xZzF/8nf+LjrfUE/dS1aRHM7uMDD0cgCArhjtfneFePrMxt+Z7W8yNBzSarub8qsfhaVNikV7Es7oaeTygfjQXTi2n4AFkir3fM07J08RpWhl5M8f8uWTCuvFUYAw00gq55typqmnbkmJa2VIUy/iQf+cMCP7abz4/jNhUzUR3qA7TV4oMRgTdIEDUp63YF8dOC+JH8XxYrCVeHXV6fLCwmesdMzl0lB2VTEKMfLbXhOmF5g7P9y/16VCcN8UBuZlbyYfn+GAxJOSbeHi5HshOKfoSuD7Jz+3WQZpNavOWjIFExKIU38/CvnJCOP7XBCqpSTAgMBAAECggEAYeWokWRE3TpvwiOZnUpR/aVMdVi75a3ROL5XIpqPV61B+t/bU3cEpl0GF9C5pUeiRi0IoStZb3mI9D1KPW/REKyUWkhabQO1gFYbTnRlkNOn6MILzKX4cwJjDaZeeo4EBPU7N+qHyOOXrU6hdH5FfxhMdV983ajm5eeuupxER1C2kAcIklTeVpTX6EKOgZb5LBp5ssOVm2P42pOauvcRozRcvZmqnErXmukv0H4l3EVNt4rHpTn9riHUC63e8JfiYzVaF6zuNUxv6nHEft0/SRMw11XSTnNfDzcKqgjz6ksFBS/6eQQYKESk+ONC53HUuYHFAknkwsPupDCT2W8FIQKBgQDLHT/xCU3nxGr4vFKBDNaO2D5oK20ECbBO4oDvLWWmQG7f+6TsMy8PgVdMnoL4RfqGlwFAKEpS6KVFHnBVqnNEhcdy9uCI7x7Xx8UnyUtxj1EDTm76uta9Ki9OrlqB6tImDM9+Ya3vGktW37ht4WOx2OsJRhG1dbf6RLwFlH7DWwKBgQDFBxvi5I1BR6hg6Tj7xd2SqOT2Y+BED3xuSYENhWbmMhLJDResaB7mjztbxlYaY2mOE0holWm2uDmVFFhMh4jYXik4hYH8nmDzq9mDpZCZ9pyjYqnAP8THoAa8EbgrUWB8A6BPH4iL3KbMnBfBKY0pIr2xrvnjQjNBAgta7KDRKQKBgCe6oe4wxrdF2TKsC2tIqpMoQxS3Icy/ZGgZr+SYuaBKTCWtoDW/UT40K3JGMxIDBhzbXphBCUCsVt9tM8Xd4EwP6tJW7dZ7B0pnve2pVwNwaAVAiz6p2yUHIle+jN+Koe5lZRSwYIg7WW81tWpwwsJfzqFyvjYDP6hJV4mz4ROvAoGAaRcdnKvjXApomShMqJ4lTPChD3q+SA8qg3jZSOj6tZXHx00gb2kp8jg7pPvpOTIFPy6x1Ha9aCRjMk0ju84fA6lVuzwa1S907wOehUVuF3Eeo1cgy9Y3k3KbpPyeixxgpkUY4JslLdSHc2NemD0dee951qhJyRmqVOZOQDUuoeECgYEAqBw2cAFk3vM97WY06TSldGA8ajVHx3BYRjj+zl62NTQthy8fw3tqxb3c5e8toOmZWKjZvDhg2TRLhsDDQWEYg3LZG87REqVIjgEPcpjNLidjygGX8n3JF2o0O5I/EMvl0s/+LVQONfduOBvhwDqr8QNisbLsyneiAq7umewMolo="
+ public-key: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnFMmIVanMxsW5S/qP8Wcxf/J3/i4631BP3UtWkRzO7jAw9HIAgK4Y7X53hXj6zMbfme1vMjQc0mq7m/KrH4WlTYpFexLO6Gnk8oH40F04tp+ABZIq93zNOydPEaVoZeTPH/LlkwrrxVGAMNNIKuebcqapp25JiWtlSFMv4kH/nDAj+2m8+P4zYVM1Ed6gO01eKDEYE3SBA1Ket2BfHTgviR/F8WKwlXh11enywsJnrHTM5dJQdlUxCjHy214TpheYOz/cv9elQnDfFAbmZW8mH5/hgMSTkm3h4uR7ITin6Erg+yc/t1kGaTWrzloyBRMSiFN/Pwr5yQjj+1wQqqUkwIDAQAB"
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index e52be1a5..68d6a140 100644
--- a/pom.xml
+++ b/pom.xml
@@ -15,6 +15,7 @@
storage
tools
+ tools/activate-tool
pom
融合各工具的项目
diff --git a/tools/activate-tool/pom.xml b/tools/activate-tool/pom.xml
new file mode 100644
index 00000000..40ef358d
--- /dev/null
+++ b/tools/activate-tool/pom.xml
@@ -0,0 +1,50 @@
+
+
+ 4.0.0
+
+ com.njcn.gather
+ CN_Gather
+ 1.0.0
+
+
+ activate-tool
+
+
+ 8
+ 8
+ UTF-8
+
+
+
+
+ com.njcn
+ njcn-common
+ 0.0.1
+
+
+
+ com.njcn
+ spingboot2.3.12
+ 2.3.12
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tools/activate-tool/src/main/java/com/njcn/gather/tool/active/ActivateToolApplication.java b/tools/activate-tool/src/main/java/com/njcn/gather/tool/active/ActivateToolApplication.java
new file mode 100644
index 00000000..4a308e79
--- /dev/null
+++ b/tools/activate-tool/src/main/java/com/njcn/gather/tool/active/ActivateToolApplication.java
@@ -0,0 +1,15 @@
+package com.njcn.gather.tool.active;
+
+import com.njcn.gather.tool.active.config.RSAProperties;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+
+@EnableConfigurationProperties(RSAProperties.class)
+@SpringBootApplication
+public class ActivateToolApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ActivateToolApplication.class, args);
+ }
+}
diff --git a/tools/activate-tool/src/main/java/com/njcn/gather/tool/active/config/RSAProperties.java b/tools/activate-tool/src/main/java/com/njcn/gather/tool/active/config/RSAProperties.java
new file mode 100644
index 00000000..c24e4700
--- /dev/null
+++ b/tools/activate-tool/src/main/java/com/njcn/gather/tool/active/config/RSAProperties.java
@@ -0,0 +1,17 @@
+package com.njcn.gather.tool.active.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+@Data
+@ConfigurationProperties(prefix = "rsa")
+public class RSAProperties {
+ /**
+ * RSA公钥
+ */
+ private String publicKey;
+ /**
+ * RSA私钥
+ */
+ private String privateKey;
+}
diff --git a/tools/activate-tool/src/main/java/com/njcn/gather/tool/active/controller/ActivateController.java b/tools/activate-tool/src/main/java/com/njcn/gather/tool/active/controller/ActivateController.java
new file mode 100644
index 00000000..68ff7267
--- /dev/null
+++ b/tools/activate-tool/src/main/java/com/njcn/gather/tool/active/controller/ActivateController.java
@@ -0,0 +1,42 @@
+package com.njcn.gather.tool.active.controller;
+
+import com.njcn.common.pojo.enums.response.CommonResponseEnum;
+import com.njcn.common.pojo.response.HttpResult;
+import com.njcn.gather.tool.active.service.ActivateService;
+import com.njcn.web.controller.BaseController;
+import com.njcn.web.utils.HttpResultUtil;
+import io.swagger.annotations.*;
+import lombok.Data;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@Slf4j
+@Api(tags = "设备激活管理")
+@RestController
+@RequestMapping("/activate")
+@RequiredArgsConstructor
+public class ActivateController extends BaseController {
+
+ private final ActivateService activateService;
+
+ @ApiOperation("生成设备激活码")
+ @ApiImplicitParam(name = "params", value = "参数", required = true, dataType = "ApplicationCodeParams")
+ @PostMapping("/generateActivationCode")
+ public HttpResult generateActivationCode(@RequestBody ApplicationCodeParams params) {
+ String activationCode = activateService.generateActivationCode(params.getApplicationCode(), params.getPermanently());
+ return HttpResultUtil.assembleResult(CommonResponseEnum.SUCCESS.getCode(), activationCode, "");
+ }
+
+ @ApiModel("生成设备激活码参数")
+ @Data
+ public static class ApplicationCodeParams {
+ @ApiModelProperty(value = "设备申请码", required = true)
+ private String applicationCode;
+ @ApiModelProperty(value = "是否永久激活", example = "1", required = true)
+ private int permanently;
+ }
+}
\ No newline at end of file
diff --git a/tools/activate-tool/src/main/java/com/njcn/gather/tool/active/service/ActivateService.java b/tools/activate-tool/src/main/java/com/njcn/gather/tool/active/service/ActivateService.java
new file mode 100644
index 00000000..e3b2af08
--- /dev/null
+++ b/tools/activate-tool/src/main/java/com/njcn/gather/tool/active/service/ActivateService.java
@@ -0,0 +1,15 @@
+package com.njcn.gather.tool.active.service;
+
+public interface ActivateService {
+
+ /**
+ * 生成设备激活码
+ *
+ * @param applicationCode 申请码
+ * @param permanently 是否永久激活
+ * @return
+ */
+ String generateActivationCode(String applicationCode, int permanently);
+
+
+}
diff --git a/tools/activate-tool/src/main/java/com/njcn/gather/tool/active/service/impl/ActivateServiceImpl.java b/tools/activate-tool/src/main/java/com/njcn/gather/tool/active/service/impl/ActivateServiceImpl.java
new file mode 100644
index 00000000..1dd1bc06
--- /dev/null
+++ b/tools/activate-tool/src/main/java/com/njcn/gather/tool/active/service/impl/ActivateServiceImpl.java
@@ -0,0 +1,65 @@
+package com.njcn.gather.tool.active.service.impl;
+
+import cn.hutool.json.JSONUtil;
+import com.njcn.common.pojo.enums.response.CommonResponseEnum;
+import com.njcn.common.pojo.exception.BusinessException;
+import com.njcn.common.utils.RSAUtil;
+import com.njcn.gather.tool.active.config.RSAProperties;
+import com.njcn.gather.tool.active.service.ActivateService;
+import com.njcn.gather.tool.active.vo.ActivationCodePlaintext;
+import com.njcn.gather.tool.active.vo.ActivationModule;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+@RequiredArgsConstructor
+@Slf4j
+@Service
+public class ActivateServiceImpl implements ActivateService {
+
+ private final RSAProperties rsaProperties;
+
+
+ @Override
+ public String generateActivationCode(String applicationCode, int permanently) {
+ // RSA 解密
+ String plaintext;
+ try {
+ plaintext = RSAUtil.decrypt(applicationCode, RSAUtil.stringToPrivateKey(rsaProperties.getPrivateKey()));
+ } catch (Exception e) {
+ log.error("申请码解密失败", e);
+ throw new BusinessException(CommonResponseEnum.FAIL, "无效的申请码");
+ }
+ ActivationCodePlaintext activationCodePlaintext = JSONUtil.toBean(plaintext, ActivationCodePlaintext.class);
+ if (activationCodePlaintext == null) {
+ log.error("申请码内容为空");
+ throw new BusinessException(CommonResponseEnum.FAIL, "无效的申请码");
+ }
+ // 激活码明文
+ ActivationModule contrast = activationCodePlaintext.getContrast();
+ ActivationModule simulate = activationCodePlaintext.getSimulate();
+ ActivationModule digital = activationCodePlaintext.getDigital();
+ if (contrast.isApply()) {
+ contrast.setPermanently(permanently);
+ activationCodePlaintext.setContrast(contrast);
+ }
+ if (simulate.isApply()) {
+ simulate.setPermanently(permanently);
+ activationCodePlaintext.setSimulate(simulate);
+ }
+ if (digital.isApply()) {
+ digital.setPermanently(permanently);
+ activationCodePlaintext.setDigital(digital);
+ }
+ // RSA 加密
+ String jsonStr = JSONUtil.toJsonStr(activationCodePlaintext);
+ log.info("生成激活码明文:{}", jsonStr);
+ try {
+ return RSAUtil.encrypt(jsonStr, RSAUtil.stringToPublicKey(rsaProperties.getPublicKey()));
+ } catch (Exception e) {
+ log.error("生成激活码失败", e);
+ throw new BusinessException(CommonResponseEnum.FAIL, "生成激活码失败");
+ }
+ }
+
+}
diff --git a/tools/activate-tool/src/main/java/com/njcn/gather/tool/active/vo/ActivationCodePlaintext.java b/tools/activate-tool/src/main/java/com/njcn/gather/tool/active/vo/ActivationCodePlaintext.java
new file mode 100644
index 00000000..f01a08f4
--- /dev/null
+++ b/tools/activate-tool/src/main/java/com/njcn/gather/tool/active/vo/ActivationCodePlaintext.java
@@ -0,0 +1,28 @@
+package com.njcn.gather.tool.active.vo;
+
+import lombok.Data;
+
+@Data
+public class ActivationCodePlaintext {
+ /**
+ * mac地址
+ */
+ private String macAddress;
+
+ /**
+ * 模拟式模块
+ */
+ private ActivationModule simulate;
+
+ /**
+ * 数字式模块
+ */
+ private ActivationModule digital;
+
+ /**
+ * 比对式模块
+ */
+ private ActivationModule contrast;
+
+
+}
diff --git a/tools/activate-tool/src/main/java/com/njcn/gather/tool/active/vo/ActivationModule.java b/tools/activate-tool/src/main/java/com/njcn/gather/tool/active/vo/ActivationModule.java
new file mode 100644
index 00000000..72348ca0
--- /dev/null
+++ b/tools/activate-tool/src/main/java/com/njcn/gather/tool/active/vo/ActivationModule.java
@@ -0,0 +1,15 @@
+package com.njcn.gather.tool.active.vo;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class ActivationModule extends ApplicationModule {
+ /**
+ * 是否永久授权
+ */
+ private int permanently;
+
+
+}
\ No newline at end of file
diff --git a/tools/activate-tool/src/main/java/com/njcn/gather/tool/active/vo/ApplicationCodePlaintext.java b/tools/activate-tool/src/main/java/com/njcn/gather/tool/active/vo/ApplicationCodePlaintext.java
new file mode 100644
index 00000000..de03d39a
--- /dev/null
+++ b/tools/activate-tool/src/main/java/com/njcn/gather/tool/active/vo/ApplicationCodePlaintext.java
@@ -0,0 +1,28 @@
+package com.njcn.gather.tool.active.vo;
+
+import lombok.Data;
+
+@Data
+public class ApplicationCodePlaintext {
+ /**
+ * mac地址
+ */
+ private String macAddress;
+
+ /**
+ * 模拟式模块
+ */
+ private ApplicationModule simulate;
+
+ /**
+ * 数字式模块
+ */
+ private ApplicationModule digital;
+
+ /**
+ * 比对式模块
+ */
+ private ApplicationModule contrast;
+
+
+}
diff --git a/tools/activate-tool/src/main/java/com/njcn/gather/tool/active/vo/ApplicationModule.java b/tools/activate-tool/src/main/java/com/njcn/gather/tool/active/vo/ApplicationModule.java
new file mode 100644
index 00000000..a11876b2
--- /dev/null
+++ b/tools/activate-tool/src/main/java/com/njcn/gather/tool/active/vo/ApplicationModule.java
@@ -0,0 +1,15 @@
+package com.njcn.gather.tool.active.vo;
+
+import lombok.Data;
+
+@Data
+public class ApplicationModule {
+ /**
+ * 是否申请 1是 0否
+ */
+ private Integer apply;
+
+ public boolean isApply() {
+ return apply == 1;
+ }
+}
\ No newline at end of file
diff --git a/tools/activate-tool/src/main/resources/application.yml b/tools/activate-tool/src/main/resources/application.yml
new file mode 100644
index 00000000..3e3b7eb2
--- /dev/null
+++ b/tools/activate-tool/src/main/resources/application.yml
@@ -0,0 +1,8 @@
+server:
+ port: 8888
+spring:
+ application:
+ name: active-tool
+rsa:
+ private-key: "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCcUyYhVqczGxblL+o/xZzF/8nf+LjrfUE/dS1aRHM7uMDD0cgCArhjtfneFePrMxt+Z7W8yNBzSarub8qsfhaVNikV7Es7oaeTygfjQXTi2n4AFkir3fM07J08RpWhl5M8f8uWTCuvFUYAw00gq55typqmnbkmJa2VIUy/iQf+cMCP7abz4/jNhUzUR3qA7TV4oMRgTdIEDUp63YF8dOC+JH8XxYrCVeHXV6fLCwmesdMzl0lB2VTEKMfLbXhOmF5g7P9y/16VCcN8UBuZlbyYfn+GAxJOSbeHi5HshOKfoSuD7Jz+3WQZpNavOWjIFExKIU38/CvnJCOP7XBCqpSTAgMBAAECggEAYeWokWRE3TpvwiOZnUpR/aVMdVi75a3ROL5XIpqPV61B+t/bU3cEpl0GF9C5pUeiRi0IoStZb3mI9D1KPW/REKyUWkhabQO1gFYbTnRlkNOn6MILzKX4cwJjDaZeeo4EBPU7N+qHyOOXrU6hdH5FfxhMdV983ajm5eeuupxER1C2kAcIklTeVpTX6EKOgZb5LBp5ssOVm2P42pOauvcRozRcvZmqnErXmukv0H4l3EVNt4rHpTn9riHUC63e8JfiYzVaF6zuNUxv6nHEft0/SRMw11XSTnNfDzcKqgjz6ksFBS/6eQQYKESk+ONC53HUuYHFAknkwsPupDCT2W8FIQKBgQDLHT/xCU3nxGr4vFKBDNaO2D5oK20ECbBO4oDvLWWmQG7f+6TsMy8PgVdMnoL4RfqGlwFAKEpS6KVFHnBVqnNEhcdy9uCI7x7Xx8UnyUtxj1EDTm76uta9Ki9OrlqB6tImDM9+Ya3vGktW37ht4WOx2OsJRhG1dbf6RLwFlH7DWwKBgQDFBxvi5I1BR6hg6Tj7xd2SqOT2Y+BED3xuSYENhWbmMhLJDResaB7mjztbxlYaY2mOE0holWm2uDmVFFhMh4jYXik4hYH8nmDzq9mDpZCZ9pyjYqnAP8THoAa8EbgrUWB8A6BPH4iL3KbMnBfBKY0pIr2xrvnjQjNBAgta7KDRKQKBgCe6oe4wxrdF2TKsC2tIqpMoQxS3Icy/ZGgZr+SYuaBKTCWtoDW/UT40K3JGMxIDBhzbXphBCUCsVt9tM8Xd4EwP6tJW7dZ7B0pnve2pVwNwaAVAiz6p2yUHIle+jN+Koe5lZRSwYIg7WW81tWpwwsJfzqFyvjYDP6hJV4mz4ROvAoGAaRcdnKvjXApomShMqJ4lTPChD3q+SA8qg3jZSOj6tZXHx00gb2kp8jg7pPvpOTIFPy6x1Ha9aCRjMk0ju84fA6lVuzwa1S907wOehUVuF3Eeo1cgy9Y3k3KbpPyeixxgpkUY4JslLdSHc2NemD0dee951qhJyRmqVOZOQDUuoeECgYEAqBw2cAFk3vM97WY06TSldGA8ajVHx3BYRjj+zl62NTQthy8fw3tqxb3c5e8toOmZWKjZvDhg2TRLhsDDQWEYg3LZG87REqVIjgEPcpjNLidjygGX8n3JF2o0O5I/EMvl0s/+LVQONfduOBvhwDqr8QNisbLsyneiAq7umewMolo="
+ public-key: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnFMmIVanMxsW5S/qP8Wcxf/J3/i4631BP3UtWkRzO7jAw9HIAgK4Y7X53hXj6zMbfme1vMjQc0mq7m/KrH4WlTYpFexLO6Gnk8oH40F04tp+ABZIq93zNOydPEaVoZeTPH/LlkwrrxVGAMNNIKuebcqapp25JiWtlSFMv4kH/nDAj+2m8+P4zYVM1Ed6gO01eKDEYE3SBA1Ket2BfHTgviR/F8WKwlXh11enywsJnrHTM5dJQdlUxCjHy214TpheYOz/cv9elQnDfFAbmZW8mH5/hgMSTkm3h4uR7ITin6Erg+yc/t1kGaTWrzloyBRMSiFN/Pwr5yQjj+1wQqqUkwIDAQAB"
\ No newline at end of file
diff --git a/tools/pom.xml b/tools/pom.xml
index 68751820..a909ada9 100644
--- a/tools/pom.xml
+++ b/tools/pom.xml
@@ -18,6 +18,7 @@
report-generator
wave-comtrade
+ activate-tool
\ No newline at end of file