ADD: 程序激活流程:1、生成设备申请码;2、验证设备激活码;3、读取许可信息;4、激活码生成工具。
This commit is contained in:
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -6,12 +6,12 @@ spring:
|
|||||||
datasource:
|
datasource:
|
||||||
druid:
|
druid:
|
||||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
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
|
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:13306/pqs9100member?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
|
|
||||||
username: root
|
username: root
|
||||||
password: njcnpqs
|
password: njcnpqs
|
||||||
|
# url: jdbc:mysql://localhost:3306/pqs91001?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=CTT
|
||||||
|
# username: root
|
||||||
|
# password: root
|
||||||
#初始化建立物理连接的个数、最小、最大连接数
|
#初始化建立物理连接的个数、最小、最大连接数
|
||||||
initial-size: 5
|
initial-size: 5
|
||||||
min-idle: 5
|
min-idle: 5
|
||||||
@@ -118,3 +118,7 @@ power-quality:
|
|||||||
harmonic-times: 50 # 谐波次数
|
harmonic-times: 50 # 谐波次数
|
||||||
ib-add: false # 电流基波叠加标志
|
ib-add: false # 电流基波叠加标志
|
||||||
uharm-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"
|
||||||
1
pom.xml
1
pom.xml
@@ -15,6 +15,7 @@
|
|||||||
<module>storage</module>
|
<module>storage</module>
|
||||||
<!-- <module>event_smart</module>-->
|
<!-- <module>event_smart</module>-->
|
||||||
<module>tools</module>
|
<module>tools</module>
|
||||||
|
<module>tools/activate-tool</module>
|
||||||
</modules>
|
</modules>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<name>融合各工具的项目</name>
|
<name>融合各工具的项目</name>
|
||||||
|
|||||||
50
tools/activate-tool/pom.xml
Normal file
50
tools/activate-tool/pom.xml
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>com.njcn.gather</groupId>
|
||||||
|
<artifactId>CN_Gather</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>activate-tool</artifactId>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.njcn</groupId>
|
||||||
|
<artifactId>njcn-common</artifactId>
|
||||||
|
<version>0.0.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.njcn</groupId>
|
||||||
|
<artifactId>spingboot2.3.12</artifactId>
|
||||||
|
<version>2.3.12</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<excludes>
|
||||||
|
<exclude>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
</exclude>
|
||||||
|
</excludes>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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, "生成激活码失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
8
tools/activate-tool/src/main/resources/application.yml
Normal file
8
tools/activate-tool/src/main/resources/application.yml
Normal file
@@ -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"
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
<modules>
|
<modules>
|
||||||
<module>report-generator</module>
|
<module>report-generator</module>
|
||||||
<module>wave-comtrade</module>
|
<module>wave-comtrade</module>
|
||||||
|
<module>activate-tool</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
Reference in New Issue
Block a user