src/main/java/com/zy/common/service/CommonService.java
@@ -156,6 +156,8 @@ return null; } /** * 检索库位号 * @@ -290,21 +292,6 @@ } } // // 靠近摆放规则 --- 空托 //分离版 // if (staDescId == 10 && Utils.BooleanWhsTypeStaIoType(whsType)) { // List<LocMast> locMasts = locMastService.selectList(new EntityWrapper<LocMast>().eq("row1", nearRow).eq("loc_sts", "O")); // for (LocMast locMast1:locMasts){ // if (VersionUtils.locMoveCheckLocTypeComplete(locMast1, locTypeDto)) { // continue; // } // String shallowLoc = Utils.getDeepLoc(slaveProperties,locMast1.getLocNo()); // LocMast locMast2 = locMastService.selectOne(new EntityWrapper<LocMast>().eq("loc_no",shallowLoc)); // if (!Cools.isEmpty(locMast2) && locMast2.getLocSts().equals("D")){ // locMast = locMast1; // break; // } // } // } // 靠近摆放规则 --- 空托 //互通版 if (staDescId == 10 && Utils.BooleanWhsTypeStaIoType(rowLastno)) { src/main/java/com/zy/system/controller/LicenseCreatorController.java
@@ -4,7 +4,6 @@ import com.core.common.R; import com.zy.system.entity.license.*; import com.zy.system.timer.LicenseTimer; import de.schlichtherle.license.LicenseContent; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.MediaType; @@ -15,7 +14,6 @@ import java.io.File; import java.io.IOException; import java.util.Date; /** * @@ -27,7 +25,6 @@ @Value("${license.licensePath}") private String licensePath; @Autowired private LicenseCheckListener licenseCheckListener; @Autowired @@ -50,7 +47,7 @@ if (osName.startsWith("windows")) { abstractServerInfos = new WindowsServerInfos(); } else if (osName.startsWith("linux")) { // abstractServerInfos = new LinuxServerInfos(); abstractServerInfos = new LinuxServerInfos(); }else{//其他服务器类型 abstractServerInfos = new WindowsServerInfos(); } @@ -99,4 +96,10 @@ return R.error("许可证更新失败"); } @RequestMapping(value = "/activate") public R activate() { licenseTimer.timer(); return R.ok(); } } src/main/java/com/zy/system/entity/LicenseInfos.java
New file @@ -0,0 +1,56 @@ package com.zy.system.entity; import com.core.common.Cools;import com.baomidou.mybatisplus.annotations.TableId; import com.baomidou.mybatisplus.enums.IdType; import java.text.SimpleDateFormat; import java.util.Date; import com.baomidou.mybatisplus.annotations.TableField; import org.springframework.format.annotation.DateTimeFormat; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import com.baomidou.mybatisplus.annotations.TableName; import java.io.Serializable; @Data @TableName("sys_license_infos") public class LicenseInfos implements Serializable { private static final long serialVersionUID = 1L; @ApiModelProperty(value= "") @TableId(value = "id", type = IdType.AUTO) private Integer id; @ApiModelProperty(value= "") private String license; @ApiModelProperty(value= "") private String licenseTime; @ApiModelProperty(value= "") @TableField("create_time") @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") private Date createTime; public LicenseInfos() {} public LicenseInfos(String license,Date createTime) { this.license = license; this.createTime = createTime; } // LicenseInfos licenseInfos = new LicenseInfos( // null, // // null // // ); public String getCreateTime$(){ if (Cools.isEmpty(this.createTime)){ return ""; } return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.createTime); } } src/main/java/com/zy/system/entity/license/AbstractServerInfos.java
@@ -23,7 +23,7 @@ LicenseCheck result = new LicenseCheck(); try { result.setIpAddress(this.getIpAddress()); // result.setIpAddress(this.getIpAddress()); result.setMacAddress(this.getMacAddress()); result.setCpuSerial(this.getCPUSerial()); result.setMainBoardSerial(this.getMainBoardSerial()); src/main/java/com/zy/system/entity/license/CustomLicenseManager.java
@@ -194,7 +194,7 @@ if (osName.startsWith("windows")) { abstractServerInfos = new WindowsServerInfos(); } else if (osName.startsWith("linux")) { // abstractServerInfos = new LinuxServerInfos(); abstractServerInfos = new LinuxServerInfos(); }else{//其他服务器类型 abstractServerInfos = new WindowsServerInfos(); } src/main/java/com/zy/system/entity/license/LicenseCheckListener.java
@@ -1,6 +1,8 @@ package com.zy.system.entity.license; import com.core.common.Cools; import com.zy.system.entity.LicenseInfos; import com.zy.system.service.LicenseInfosService; import com.zy.system.timer.LicenseTimer; import de.schlichtherle.license.LicenseContent; import org.apache.logging.log4j.LogManager; @@ -53,6 +55,8 @@ private String publicKeysStorePath; @Autowired private LicenseTimer licenseTimer; @Autowired private LicenseInfosService licenseInfosService; @Override public void onApplicationEvent(ContextRefreshedEvent event) { @@ -69,12 +73,11 @@ logger.info("++++++++ 开始加载许可证 ++++++++"); try { // String publicKeysStoreFileName = this.getClass().getClassLoader().getResource(publicKeysStorePath).getPath(); // File publicKeysStoreFile = new File(publicKeysStoreFileName); // // String licensePathFileName = this.getClass().getClassLoader().getResource(licensePath).getPath(); // File licensePathFile = new File(licensePathFileName); licenseTimer.getRemoteLicense(); } catch (Exception e) { } try { LicenseVerifyParam param = new LicenseVerifyParam(); param.setSubject(subject); param.setPublicAlias(publicAlias); @@ -83,8 +86,15 @@ param.setPublicKeysStorePath(publicKeysStorePath); LicenseVerify licenseVerify = new LicenseVerify(); LicenseInfos latestLicense = licenseInfosService.getLatestLicense(); if (latestLicense == null) { logger.info("许可证不存在"); return false; } //安装证书 LicenseContent install = licenseVerify.install(param); LicenseContent install = licenseVerify.install(param, latestLicense.getLicense()); logger.info("++++++++ 许可证加载结束 ++++++++"); @@ -103,6 +113,7 @@ return install != null; } catch (Exception e) { e.printStackTrace(); return false; } } src/main/java/com/zy/system/entity/license/LicenseVerify.java
@@ -3,14 +3,15 @@ import de.schlichtherle.license.*; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.tomcat.util.http.fileupload.IOUtils; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.text.DateFormat; import java.text.MessageFormat; import java.text.SimpleDateFormat; import java.util.Base64; import java.util.prefs.Preferences; /** @@ -22,22 +23,18 @@ /** * 安装License证书 */ public synchronized LicenseContent install(LicenseVerifyParam param){ public synchronized LicenseContent install(LicenseVerifyParam param, String license) { LicenseContent result = null; DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //1. 安装证书 try{ LicenseManager licenseManager = LicenseManagerHolder.getInstance(initLicenseParam(param)); LicenseParam licenseParam = initLicenseParam(param); LicenseManager licenseManager = LicenseManagerHolder.getInstance(licenseParam); licenseManager.uninstall(); InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(param.getLicensePath()); File file = new File(param.getLicensePath()); try (FileOutputStream out = new FileOutputStream(file)) { IOUtils.copy(inputStream, out); } result = licenseManager.install(new File(param.getLicensePath())); File tempFileFromBase64 = createTempFileFromBase64(license); result = licenseManager.install(tempFileFromBase64); logger.info(MessageFormat.format("许可证加载成功,许可证有效期:{0} - {1}",format.format(result.getNotBefore()),format.format(result.getNotAfter()))); }catch (Exception e){ logger.error("许可证加载失败!",e); @@ -54,11 +51,6 @@ LicenseManager licenseManager = LicenseManagerHolder.getInstance(null); DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); if (!updateSystemTime()) { //时间更新失败,系统时间被更改 return false; } LicenseContent licenseContent = licenseManager.verify(); logger.info(MessageFormat.format("许可证校验通过,许可证有效期:{0} - {1}",format.format(licenseContent.getNotBefore()),format.format(licenseContent.getNotAfter()))); return true; @@ -73,11 +65,6 @@ */ public LicenseContent getVerifyInfo(){ LicenseManager licenseManager = LicenseManagerHolder.getInstance(null); if (!updateSystemTime()) { //时间更新失败,系统时间被更改 return null; } //校验证书 try { @@ -112,31 +99,28 @@ } /** * 更新时间到注册表中 * 将Base64字符串转换为临时文件 * @param base64String Base64编码的字符串 * @param filePrefix 文件名前缀(例如 "license_") * @param fileSuffix 文件后缀(例如 ".lic") * @return 生成的临时File对象(自动在JVM退出时删除) * @throws IOException */ private boolean updateSystemTime() { // 获取用户根节点 Preferences userRoot = Preferences.userRoot(); // 获取指定路径下的节点 Preferences node = userRoot.node("/zhongyang"); String key = "time"; // 读取注册表 String value = node.get(key, null); if (value != null) { long originTime = Long.parseLong(value); long now = System.currentTimeMillis(); long diff = now - originTime;//现在时间 - 源时间 = 时间差 if (diff > 0) { //时间差大于0才允许更新注册表时间 node.put(key, String.valueOf(System.currentTimeMillis())); return true; public File base64ToTempFile(String base64String, String filePrefix, String fileSuffix) throws IOException { // 解码Base64 byte[] decodedBytes = Base64.getDecoder().decode(base64String); // 创建临时文件 Path tempPath = Files.createTempFile(filePrefix, fileSuffix); // 写入内容 Files.write(tempPath, decodedBytes); // 设置JVM退出时自动删除 tempPath.toFile().deleteOnExit(); return tempPath.toFile(); } }else { // 写入注册表 node.put(key, String.valueOf(System.currentTimeMillis())); return true; } return false; public File createTempFileFromBase64(String base64Data) throws IOException { return base64ToTempFile(base64Data, "temp_license_", ".bin"); } } src/main/java/com/zy/system/entity/license/LinuxServerInfos.java
New file @@ -0,0 +1,91 @@ package com.zy.system.entity.license; import com.core.common.Cools; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.InetAddress; import java.util.List; import java.util.stream.Collectors; /** * 用于获取客户Linux服务器的基本信息 */ public class LinuxServerInfos extends AbstractServerInfos { @Override protected List<String> getIpAddress() throws Exception { List<String> result = null; //获取所有网络接口 List<InetAddress> inetAddresses = getLocalAllInetAddress(); if (inetAddresses != null && inetAddresses.size() > 0) { result = inetAddresses.stream().map(InetAddress::getHostAddress).distinct().map(String::toLowerCase).collect(Collectors.toList()); } return result; } @Override protected List<String> getMacAddress() throws Exception { List<String> result = null; //1. 获取所有网络接口 List<InetAddress> inetAddresses = getLocalAllInetAddress(); if (inetAddresses != null && inetAddresses.size() > 0) { //2. 获取所有网络接口的Mac地址 result = inetAddresses.stream().map(this::getMacByInetAddress).distinct().collect(Collectors.toList()); } return result; } @Override protected String getCPUSerial() throws Exception { //序列号 String serialNumber = ""; //使用dmidecode命令获取CPU序列号 String[] shell = {"/bin/bash", "-c", "dmidecode -t processor | grep 'ID' | awk -F ':' '{print $2}' | head -n 1"}; Process process = Runtime.getRuntime().exec(shell); process.getOutputStream().close(); BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); if (null == reader.readLine()) { return serialNumber; } String line = reader.readLine().trim(); if (!Cools.isEmpty(line)) { serialNumber = line; } reader.close(); return serialNumber; } @Override protected String getMainBoardSerial() throws Exception { //序列号 String serialNumber = ""; //使用dmidecode命令获取主板序列号 String[] shell = {"/bin/bash", "-c", "dmidecode | grep 'Serial Number' | awk -F ':' '{print $2}' | head -n 1"}; Process process = Runtime.getRuntime().exec(shell); process.getOutputStream().close(); BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); if (null == reader.readLine()) { return serialNumber; } String line = reader.readLine().trim(); if (!Cools.isEmpty(line)) { serialNumber = line; } reader.close(); return serialNumber; } } src/main/java/com/zy/system/mapper/LicenseInfosMapper.java
New file @@ -0,0 +1,14 @@ package com.zy.system.mapper; import com.zy.system.entity.LicenseInfos; import com.baomidou.mybatisplus.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; @Mapper @Repository public interface LicenseInfosMapper extends BaseMapper<LicenseInfos> { LicenseInfos getLatestLicense(); } src/main/java/com/zy/system/service/LicenseInfosService.java
New file @@ -0,0 +1,10 @@ package com.zy.system.service; import com.zy.system.entity.LicenseInfos; import com.baomidou.mybatisplus.service.IService; public interface LicenseInfosService extends IService<LicenseInfos> { LicenseInfos getLatestLicense(); } src/main/java/com/zy/system/service/impl/LicenseInfosServiceImpl.java
New file @@ -0,0 +1,16 @@ package com.zy.system.service.impl; import com.zy.system.mapper.LicenseInfosMapper; import com.zy.system.entity.LicenseInfos; import com.zy.system.service.LicenseInfosService; import com.baomidou.mybatisplus.service.impl.ServiceImpl; import org.springframework.stereotype.Service; @Service("licenseInfosService") public class LicenseInfosServiceImpl extends ServiceImpl<LicenseInfosMapper, LicenseInfos> implements LicenseInfosService { @Override public LicenseInfos getLatestLicense() { return this.baseMapper.getLatestLicense(); } } src/main/java/com/zy/system/timer/LicenseTimer.java
@@ -1,8 +1,20 @@ package com.zy.system.timer; import com.zy.system.entity.license.LicenseVerify; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.core.common.Cools; import com.zy.common.utils.HttpHandler; import com.zy.system.entity.LicenseInfos; import com.zy.system.entity.license.*; import com.zy.system.service.LicenseInfosService; import de.schlichtherle.license.LicenseContent; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.util.Date; import java.util.HashMap; @Component public class LicenseTimer { @@ -11,14 +23,125 @@ private static int LICENSE_DAYS = 0;//许可证天数 /** * 证书subject */ @Value("${license.subject}") private String subject; /** * 公钥别称 */ @Value("${license.publicAlias}") private String publicAlias; /** * 访问公钥库的密码 */ @Value("${license.storePass}") private String storePass; /** * 证书生成路径 */ @Value("${license.licensePath}") private String licensePath; /** * 密钥库存储路径 */ @Value("${license.publicKeysStorePath}") private String publicKeysStorePath; @Autowired private LicenseInfosService licenseInfosService; //每天晚上11点更新系统激活状态 @Scheduled(cron = "0 0 23 * * ? ") public void timer() { // System.out.println(SYSTEM_SUPPORT); try { getRemoteLicense(); } catch (Exception e) { } try { verify(); } catch (Exception e) { } } public void getRemoteLicense() { try { AbstractServerInfos abstractServerInfos = null; String osName = System.getProperty("os.name"); //根据不同操作系统类型选择不同的数据获取方法 if (osName.startsWith("windows")) { abstractServerInfos = new WindowsServerInfos(); } else if (osName.startsWith("linux")) { abstractServerInfos = new LinuxServerInfos(); }else{//其他服务器类型 abstractServerInfos = new WindowsServerInfos(); } LicenseCheck serverInfos = abstractServerInfos.getServerInfos(); HashMap<String, Object> map = new HashMap<>(); map.put("subject", subject); map.put("licenseCheck", serverInfos); String response = new HttpHandler.Builder() .setUri("http://net.zoneyung.net:9999/license") .setPath("/remoteQueryLicense") .setJson(JSON.toJSONString(map)) .build() .doPost(); JSONObject jsonObject = JSON.parseObject(response); if (jsonObject.getString("result").equals("ok")) { LicenseInfos licenseInfos = new LicenseInfos(); licenseInfos.setLicense(jsonObject.getString("data")); licenseInfos.setCreateTime(new Date()); licenseInfos.setLicenseTime(jsonObject.getString("licenseTime")); licenseInfosService.insert(licenseInfos); } } catch (Exception e) { e.printStackTrace(); } } public void verify() { LicenseInfos latestLicense = licenseInfosService.getLatestLicense(); if (latestLicense == null) { setLicenseDays(0); setSystemSupport(false); return; } LicenseVerifyParam param = new LicenseVerifyParam(); param.setSubject(subject); param.setPublicAlias(publicAlias); param.setStorePass(storePass); param.setLicensePath(licensePath); param.setPublicKeysStorePath(publicKeysStorePath); //验证许可证是否有效 LicenseVerify licenseVerify = new LicenseVerify(); boolean verify = licenseVerify.verify(); setSystemSupport(verify);//更新系统激活状态 //安装证书 LicenseContent install = licenseVerify.install(param, latestLicense.getLicense()); if (install != null) { Date start = new Date(); Date end = install.getNotAfter(); Long starTime = start.getTime(); Long endTime = end.getTime(); long num = endTime - starTime;//时间戳相差的毫秒数 int day = (int) (num / 24 / 60 / 60 / 1000); setLicenseDays(day); setSystemSupport(true); }else { setLicenseDays(0); setSystemSupport(false); } } public boolean getSystemSupport() { src/main/resources/mapper/LicenseInfosMapper.xml
New file @@ -0,0 +1,18 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.zy.system.mapper.LicenseInfosMapper"> <!-- 通用查询映射结果 --> <resultMap id="BaseResultMap" type="com.zy.system.entity.LicenseInfos"> <id column="id" property="id" /> <result column="license" property="license" /> <result column="license_time" property="licenseTime" /> <result column="create_time" property="createTime" /> </resultMap> <select id="getLatestLicense" resultMap="BaseResultMap"> select top 1 * from sys_license_infos order by create_time desc </select> </mapper> src/main/webapp/views/index.html
@@ -42,7 +42,7 @@ </ul> <ul class="layui-nav layui-layout-right"> <li class="layui-nav-item" lay-unselect id="licenseShow" style="display: none;user-select: none;"> <div style="color: red;">许可证有效期:<span id="licenseDays">29</span>天</div> <div style="color: red;">临时许可证有效期:<span id="licenseDays">29</span>天</div> </li> <li class="layui-nav-item layui-hide-xs" lay-unselect> <a ew-event="fullScreen" title="全屏"><i class="layui-icon layui-icon-screen-full"></i></a> @@ -150,6 +150,7 @@ if (days <= 30) { $("#licenseShow").show() $("#licenseDays").html(days) alert("临时许可有效期:" + days + "天") } }else { top.location.href = baseUrl + "/login";