pom.xml
@@ -9,13 +9,13 @@ <relativePath/> </parent> <groupId>com.zy</groupId> <artifactId>asrs</artifactId>t <artifactId>asrs</artifactId> <version>1.1.1</version> <packaging>war</packaging> <properties> <java.version>1.8</java.version> <cool.version>3.2.0</cool.version> <cool.version>3.4.0</cool.version> <mysql-driver.version>5.1.47</mysql-driver.version> <mybatis-plus.version>2.3.2</mybatis-plus.version> <fastjson.version>1.2.58</fastjson.version> @@ -30,13 +30,18 @@ <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> <!-- <scope>provided</scope>--> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>cn.cool</groupId> <artifactId>framework</artifactId> <version>${cool.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> src/main/java/com/zy/asrs/entity/WrkMast.java
@@ -22,6 +22,7 @@ private static final long serialVersionUID = 1L; @TableId(value = "id", type = IdType.AUTO) private Long id; /** 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; /** * @@ -25,9 +23,8 @@ @RequestMapping("/license") public class LicenseCreatorController { @Value("${license.licensePath}") private String licensePath; // @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(); } @@ -66,37 +63,43 @@ return R.ok(licenseTimer.getLicenseDays()); } @RequestMapping(value = "/updateLicense") public R updateLicense(@RequestParam("file") MultipartFile[] files){ MultipartFile file = files[0]; // @RequestMapping(value = "/updateLicense") // public R updateLicense(@RequestParam("file") MultipartFile[] files){ // MultipartFile file = files[0]; // // String licensePathFileName = this.getClass().getClassLoader().getResource(licensePath).getPath(); // File licensePathFile = new File(licensePathFileName); // //服务器端保存的文件对象 // File serverFile = new File(licensePathFile.getPath()); // if (serverFile.exists()) { // try { // serverFile.delete();//存在文件,删除 // } catch (Exception e) { // e.printStackTrace(); // } // } // // try { // //创建文件 // serverFile.createNewFile(); // //将上传的文件写入到服务器端文件内 // file.transferTo(serverFile); // } catch (IOException e) { // e.printStackTrace(); // } // // //重新加载许可证 // boolean loadedLicense = licenseCheckListener.loadLicense(); // if (loadedLicense) { // return R.ok(); // } // return R.error("许可证更新失败"); // } String licensePathFileName = this.getClass().getClassLoader().getResource(licensePath).getPath(); File licensePathFile = new File(licensePathFileName); //服务器端保存的文件对象 File serverFile = new File(licensePathFile.getPath()); if (serverFile.exists()) { try { serverFile.delete();//存在文件,删除 } catch (Exception e) { e.printStackTrace(); } } try { //创建文件 serverFile.createNewFile(); //将上传的文件写入到服务器端文件内 file.transferTo(serverFile); } catch (IOException e) { e.printStackTrace(); } //重新加载许可证 boolean loadedLicense = licenseCheckListener.loadLicense(); if (loadedLicense) { return R.ok(); } 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
@@ -40,11 +40,6 @@ @Value("${license.storePass}") private String storePass; /** * 证书生成路径 */ @Value("${license.licensePath}") private String licensePath; /** * 密钥库存储路径 @@ -65,53 +60,27 @@ //加载证书 public boolean loadLicense() { if(!Cools.isEmpty(licensePath)){ 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); LicenseVerifyParam param = new LicenseVerifyParam(); param.setSubject(subject); param.setPublicAlias(publicAlias); param.setStorePass(storePass); param.setLicensePath(licensePath); param.setPublicKeysStorePath(publicKeysStorePath); LicenseVerify licenseVerify = new LicenseVerify(); //安装证书 // LicenseContent install = licenseVerify.install(param); licenseTimer.timer(); logger.info("++++++++ 许可证加载结束 ++++++++"); logger.info("++++++++ 许可证加载标记,搜索修改 ++++++++"); licenseTimer.setSystemSupport(true); licenseTimer.setLicenseDays(9999); // licenseTimer.setSystemSupport(true); // licenseTimer.setLicenseDays(9999); return true; // licenseTimer.setSystemSupport(install!=null); // // 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); // licenseTimer.setLicenseDays(day); // } // // // return install != null; } catch (Exception e) { return false; } } licenseTimer.setSystemSupport(false); 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,25 +23,21 @@ /** * 安装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)); try { 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())); logger.info(MessageFormat.format("许可证加载成功,许可证有效期:{0} - {1}",format.format(result.getNotBefore()),format.format(result.getNotAfter()))); }catch (Exception e){ logger.error("许可证加载失败!",e); 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); } return result; @@ -53,11 +50,6 @@ try { 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()))); @@ -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; } }else { // 写入注册表 node.put(key, String.valueOf(System.currentTimeMillis())); return true; } return false; 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(); } public File createTempFileFromBase64(String base64Data) throws IOException { return base64ToTempFile(base64Data, "temp_license_", ".bin"); } } src/main/java/com/zy/system/entity/license/LicenseVerifyParam.java
@@ -23,10 +23,7 @@ */ private String storePass; /** * 证书生成路径 */ private String licensePath; /** * 密钥库存储路径 @@ -37,11 +34,10 @@ } public LicenseVerifyParam(String subject, String publicAlias, String storePass, String licensePath, String publicKeysStorePath) { public LicenseVerifyParam(String subject, String publicAlias, String storePass, String publicKeysStorePath) { this.subject = subject; this.publicAlias = publicAlias; this.storePass = storePass; this.licensePath = licensePath; this.publicKeysStorePath = publicKeysStorePath; } 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,119 @@ 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.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.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/application.yml
@@ -13,7 +13,7 @@ # url: jdbc:sqlserver://192.168.4.191:1433;databasename=integrationasrs # username: sa # password: sa@123 url: jdbc:sqlserver://localhost:1433;databasename=nbjswcs url: jdbc:sqlserver://localhost:1433;databasename=nbjsasrs # username: sa # password: sa@123 # url: jdbc:sqlserver://127.0.0.1:51433;databasename=source @@ -24,8 +24,9 @@ # password: sa@123 # url: jdbc:sqlserver://127.0.0.1:62316;databasename=source username: sa password: Skyouc#23 url: jdbc:sqlserver://127.0.0.1:1433;databasename=jsxswms password: sa@123 #password: Skyouc#23 #url: jdbc:sqlserver://127.0.0.1:1433;databasename=jsxswms mvc: static-path-pattern: /** redis: @@ -43,7 +44,7 @@ # global-config: # field-strategy: 0 configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #impl: org.apache.ibatis.logging.stdout.StdOutImpl map-underscore-to-camel-case: true cache-enabled: true call-setters-on-nulls: true @@ -63,7 +64,7 @@ subject: integrationasrs publicAlias: publicCert storePass: public_zhongyang_123456789 licensePath: license.lic # licensePath: license.lic publicKeysStorePath: publicCerts.keystore # 下位机配置 src/main/resources/license.lic
File was deleted 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/static/js/locDetl/locDetl.js
@@ -2,7 +2,7 @@ function getCol() { var cols = [ {type: 'checkbox'}, {field: 'locNo$', align: 'center',title: '库位号'} {field: 'locNo', align: 'center',title: '库位号'} ,{field: 'storeDate', align: 'center',title: '库龄(天)', sort:true} ,{field: 'matnr', align: 'center',title: '商品编号', sort:true} ,{field: 'maktx', align: 'center',title: '商品名称', sort:true}