From f19762bc440161c40d4e17c6951c073b3fbd2e1d Mon Sep 17 00:00:00 2001 From: pang.jiabao <pang_jiabao@163.com> Date: 星期三, 03 九月 2025 16:04:19 +0800 Subject: [PATCH] 许可证到期提醒,系统30分钟无操作下线账号 --- src/main/java/com/zy/system/controller/LicenseCreatorController.java | 105 ++++ src/main/java/com/zy/system/entity/license/LicenseVerifyParam.java | 48 + src/main/java/com/zy/system/entity/license/LicenseCheckListener.java | 122 ++++ src/main/java/com/zy/system/entity/license/LicenseManagerHolder.java | 22 src/main/java/com/zy/system/entity/LicenseInfos.java | 57 ++ src/main/java/com/zy/system/entity/license/CustomLicenseManager.java | 241 +++++++++ src/main/resources/publicCerts.keystore | 0 src/main/java/com/zy/system/entity/license/LicenseVerify.java | 126 ++++ src/main/resources/mapper/LicenseInfosMapper.xml | 18 src/main/java/com/zy/system/mapper/LicenseInfosMapper.java | 14 src/main/java/com/zy/system/entity/license/LicenseCreator.java | 86 +++ src/main/java/com/zy/system/entity/license/LicenseCheck.java | 45 + src/main/java/com/zy/system/entity/license/LinuxServerInfos.java | 91 +++ pom.xml | 5 src/main/java/com/zy/common/CodeRes.java | 2 src/main/java/com/zy/system/entity/license/CustomKeyStoreParam.java | 59 ++ src/main/java/com/zy/system/entity/license/LicenseCreatorParam.java | 96 +++ src/main/java/com/zy/common/web/AuthController.java | 7 src/main/java/com/zy/system/service/LicenseInfosService.java | 10 src/main/java/com/zy/system/entity/license/WindowsServerInfos.java | 85 +++ src/main/java/com/zy/system/entity/license/AbstractServerInfos.java | 111 ++++ src/main/java/com/zy/system/timer/LicenseTimer.java | 162 ++++++ src/main/resources/application.yml | 8 src/main/java/com/zy/system/service/impl/LicenseInfosServiceImpl.java | 16 24 files changed, 1,536 insertions(+), 0 deletions(-) diff --git a/pom.xml b/pom.xml index aced17e..e92480a 100644 --- a/pom.xml +++ b/pom.xml @@ -103,6 +103,11 @@ <artifactId>okhttp</artifactId> <version>3.10.0</version> </dependency> + <dependency> + <groupId>de.schlichtherle.truelicense</groupId> + <artifactId>truelicense-core</artifactId> + <version>1.33</version> + </dependency> </dependencies> <build> diff --git a/src/main/java/com/zy/common/CodeRes.java b/src/main/java/com/zy/common/CodeRes.java index fd80701..a9ea495 100644 --- a/src/main/java/com/zy/common/CodeRes.java +++ b/src/main/java/com/zy/common/CodeRes.java @@ -9,6 +9,8 @@ String USER_10002 = "10002-璐﹀彿宸茶绂佺敤"; String USER_10003 = "10003-瀵嗙爜閿欒"; + String SYSTEM_20001 = "20001-璁稿彲璇佸凡澶辨晥"; + String EXIST_500 = "500-宸ヤ綔妗�/搴撳瓨鏉$爜鏁版嵁宸插瓨鍦�"; String PICK_600 = "600-鎷f枡浠诲姟"; String NO_COMB_700 = "700-璇峰厛缁勬墭"; diff --git a/src/main/java/com/zy/common/web/AuthController.java b/src/main/java/com/zy/common/web/AuthController.java index bb270cf..c3c9b42 100644 --- a/src/main/java/com/zy/common/web/AuthController.java +++ b/src/main/java/com/zy/common/web/AuthController.java @@ -15,6 +15,7 @@ import com.zy.common.utils.RandomValidateCodeUtil; import com.zy.system.entity.*; import com.zy.system.service.*; +import com.zy.system.timer.LicenseTimer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.transaction.annotation.Transactional; @@ -45,10 +46,16 @@ private PermissionService permissionService; @Autowired private RolePermissionService rolePermissionService; + @Autowired + private LicenseTimer licenseTimer; @RequestMapping("/login.action") @ManagerAuth(value = ManagerAuth.Auth.NONE, memo = "鐧诲綍") public R loginAction(String username, String password){ + //楠岃瘉璁稿彲璇佹槸鍚︽湁鏁� + if (!licenseTimer.getSystemSupport()){ + return R.parse(CodeRes.SYSTEM_20001); + } if (username.equals("super") && password.equals(Cools.md5(superPwd))) { Map<String, Object> res = new HashMap<>(); res.put("username", username); diff --git a/src/main/java/com/zy/system/controller/LicenseCreatorController.java b/src/main/java/com/zy/system/controller/LicenseCreatorController.java new file mode 100644 index 0000000..13e2b1c --- /dev/null +++ b/src/main/java/com/zy/system/controller/LicenseCreatorController.java @@ -0,0 +1,105 @@ +package com.zy.system.controller; + +import com.core.common.Cools; +import com.core.common.R; +import com.zy.system.entity.license.*; +import com.zy.system.timer.LicenseTimer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.IOException; + +/** + * + * 鐢ㄤ簬鐢熸垚璇佷功鏂囦欢锛屼笉鑳芥斁鍦ㄧ粰瀹㈡埛閮ㄧ讲鐨勪唬鐮侀噷 + */ +@RestController +@RequestMapping("/license") +public class LicenseCreatorController { + + @Value("${license.licensePath}") + private String licensePath; + @Autowired + private LicenseCheckListener licenseCheckListener; + @Autowired + private LicenseTimer licenseTimer; + /** + * 鑾峰彇鏈嶅姟鍣ㄧ‖浠朵俊鎭� + * @param osName 鎿嶄綔绯荤粺绫诲瀷锛屽鏋滀负绌哄垯鑷姩鍒ゆ柇 + */ + @RequestMapping(value = "/getServerInfos",produces = {MediaType.APPLICATION_JSON_UTF8_VALUE}) + public LicenseCheck getServerInfos(@RequestParam(value = "osName",required = false) String osName) { + //鎿嶄綔绯荤粺绫诲瀷 + if(Cools.isEmpty(osName)){ + osName = System.getProperty("os.name"); + } + osName = osName.toLowerCase(); + + AbstractServerInfos abstractServerInfos = null; + + //鏍规嵁涓嶅悓鎿嶄綔绯荤粺绫诲瀷閫夋嫨涓嶅悓鐨勬暟鎹幏鍙栨柟娉� + if (osName.startsWith("windows")) { + abstractServerInfos = new WindowsServerInfos(); + } else if (osName.startsWith("linux")) { + abstractServerInfos = new LinuxServerInfos(); + }else{//鍏朵粬鏈嶅姟鍣ㄧ被鍨� + abstractServerInfos = new WindowsServerInfos(); + } + + return abstractServerInfos.getServerInfos(); + } + + /** + * 鑾峰彇璁稿彲璇佹湁鏁堟湡澶╂暟 + */ + @RequestMapping(value = "/getLicenseDays") + public R getLicenseDays() { + return R.ok(licenseTimer.getLicenseDays()); + } + + @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("璁稿彲璇佹洿鏂板け璐�"); + } + + @RequestMapping(value = "/activate") + public R activate() { + licenseTimer.timer(); + return R.ok(); + } + +} \ No newline at end of file diff --git a/src/main/java/com/zy/system/entity/LicenseInfos.java b/src/main/java/com/zy/system/entity/LicenseInfos.java new file mode 100644 index 0000000..891ed32 --- /dev/null +++ b/src/main/java/com/zy/system/entity/LicenseInfos.java @@ -0,0 +1,57 @@ +package com.zy.system.entity; + +import com.baomidou.mybatisplus.annotations.TableField; +import com.baomidou.mybatisplus.annotations.TableId; +import com.baomidou.mybatisplus.annotations.TableName; +import com.baomidou.mybatisplus.enums.IdType; +import com.core.common.Cools; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.io.Serializable; +import java.text.SimpleDateFormat; +import java.util.Date; + +@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); + } + + +} diff --git a/src/main/java/com/zy/system/entity/license/AbstractServerInfos.java b/src/main/java/com/zy/system/entity/license/AbstractServerInfos.java new file mode 100644 index 0000000..cb413ae --- /dev/null +++ b/src/main/java/com/zy/system/entity/license/AbstractServerInfos.java @@ -0,0 +1,111 @@ +package com.zy.system.entity.license; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; + +/** + * 鐢ㄤ簬鑾峰彇瀹㈡埛鏈嶅姟鍣ㄧ殑鍩烘湰淇℃伅锛屽锛欼P銆丮ac鍦板潃銆丆PU搴忓垪鍙枫�佷富鏉垮簭鍒楀彿绛� + */ +public abstract class AbstractServerInfos { + private static Logger logger = LogManager.getLogger(AbstractServerInfos.class); + + /** + * 缁勮闇�瑕侀澶栨牎楠岀殑License鍙傛暟 + */ + public LicenseCheck getServerInfos(){ + LicenseCheck result = new LicenseCheck(); + + try { +// result.setIpAddress(this.getIpAddress()); + result.setMacAddress(this.getMacAddress()); + result.setCpuSerial(this.getCPUSerial()); + result.setMainBoardSerial(this.getMainBoardSerial()); + }catch (Exception e){ + logger.error("鑾峰彇鏈嶅姟鍣ㄧ‖浠朵俊鎭け璐�",e); + } + + return result; + } + + /** + * 鑾峰彇IP鍦板潃 + */ + protected abstract List<String> getIpAddress() throws Exception; + + /** + * 鑾峰彇Mac鍦板潃 + */ + protected abstract List<String> getMacAddress() throws Exception; + + /** + * 鑾峰彇CPU搴忓垪鍙� + */ + protected abstract String getCPUSerial() throws Exception; + + /** + * 鑾峰彇涓绘澘搴忓垪鍙� + */ + protected abstract String getMainBoardSerial() throws Exception; + + /** + * 鑾峰彇褰撳墠鏈嶅姟鍣ㄦ墍鏈夌鍚堟潯浠剁殑InetAddress + */ + protected List<InetAddress> getLocalAllInetAddress() throws Exception { + List<InetAddress> result = new ArrayList<>(4); + + // 閬嶅巻鎵�鏈夌殑缃戠粶鎺ュ彛 + for (Enumeration networkInterfaces = NetworkInterface.getNetworkInterfaces(); networkInterfaces.hasMoreElements(); ) { + NetworkInterface iface = (NetworkInterface) networkInterfaces.nextElement(); + // 鍦ㄦ墍鏈夌殑鎺ュ彛涓嬪啀閬嶅巻IP + for (Enumeration inetAddresses = iface.getInetAddresses(); inetAddresses.hasMoreElements(); ) { + InetAddress inetAddr = (InetAddress) inetAddresses.nextElement(); + + //鎺掗櫎LoopbackAddress銆丼iteLocalAddress銆丩inkLocalAddress銆丮ulticastAddress绫诲瀷鐨処P鍦板潃 + if(!inetAddr.isLoopbackAddress() /*&& !inetAddr.isSiteLocalAddress()*/ + && !inetAddr.isLinkLocalAddress() && !inetAddr.isMulticastAddress()){ + result.add(inetAddr); + } + } + } + + return result; + } + + /** + * 鑾峰彇鏌愪釜缃戠粶鎺ュ彛鐨凪ac鍦板潃 + */ + protected String getMacByInetAddress(InetAddress inetAddr){ + try { + byte[] mac = NetworkInterface.getByInetAddress(inetAddr).getHardwareAddress(); + StringBuffer stringBuffer = new StringBuffer(); + + for(int i=0;i<mac.length;i++){ + if(i != 0) { + stringBuffer.append("-"); + } + + //灏嗗崄鍏繘鍒禸yte杞寲涓哄瓧绗︿覆 + String temp = Integer.toHexString(mac[i] & 0xff); + if(temp.length() == 1){ + stringBuffer.append("0" + temp); + }else{ + stringBuffer.append(temp); + } + } + + return stringBuffer.toString().toUpperCase(); + } catch (SocketException e) { + e.printStackTrace(); + } + + return null; + } + +} \ No newline at end of file diff --git a/src/main/java/com/zy/system/entity/license/CustomKeyStoreParam.java b/src/main/java/com/zy/system/entity/license/CustomKeyStoreParam.java new file mode 100644 index 0000000..f1cab8b --- /dev/null +++ b/src/main/java/com/zy/system/entity/license/CustomKeyStoreParam.java @@ -0,0 +1,59 @@ +package com.zy.system.entity.license; + +import de.schlichtherle.license.AbstractKeyStoreParam; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; + +/** + * 鑷畾涔塊eyStoreParam锛岀敤浜庡皢鍏閽ュ瓨鍌ㄦ枃浠跺瓨鏀惧埌鍏朵粬纾佺洏浣嶇疆鑰屼笉鏄」鐩腑 + */ +public class CustomKeyStoreParam extends AbstractKeyStoreParam { + + /** + * 鍏挜/绉侀挜鍦ㄧ鐩樹笂鐨勫瓨鍌ㄨ矾寰� + */ + private String storePath; + private String alias; + private String storePwd; + private String keyPwd; + + public CustomKeyStoreParam(Class clazz, String resource, String alias, String storePwd, String keyPwd) { + super(clazz, resource); + this.storePath = resource; + this.alias = alias; + this.storePwd = storePwd; + this.keyPwd = keyPwd; + } + + + @Override + public String getAlias() { + return alias; + } + + @Override + public String getStorePwd() { + return storePwd; + } + + @Override + public String getKeyPwd() { + return keyPwd; + } + + /** + * 澶嶅啓de.schlichtherle.license.AbstractKeyStoreParam鐨刧etStream()鏂规硶<br/> + * 鐢ㄤ簬灏嗗叕绉侀挜瀛樺偍鏂囦欢瀛樻斁鍒板叾浠栫鐩樹綅缃�屼笉鏄」鐩腑 + */ + @Override + public InputStream getStream() throws IOException { + final InputStream in = this.getClass().getClassLoader().getResourceAsStream(storePath); + if (null == in) { + throw new FileNotFoundException(storePath); + } + + return in; + } +} diff --git a/src/main/java/com/zy/system/entity/license/CustomLicenseManager.java b/src/main/java/com/zy/system/entity/license/CustomLicenseManager.java new file mode 100644 index 0000000..9a7fc6d --- /dev/null +++ b/src/main/java/com/zy/system/entity/license/CustomLicenseManager.java @@ -0,0 +1,241 @@ +package com.zy.system.entity.license; + +import com.core.common.Cools; +import de.schlichtherle.license.*; +import de.schlichtherle.xml.GenericCertificate; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.beans.XMLDecoder; +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; +import java.io.UnsupportedEncodingException; +import java.util.Date; +import java.util.List; + +/** + * 鑷畾涔塋icenseManager锛岀敤浜庡鍔犻澶栫殑鏈嶅姟鍣ㄧ‖浠朵俊鎭牎楠� + */ +public class CustomLicenseManager extends LicenseManager{ + private static Logger logger = LogManager.getLogger(CustomLicenseManager.class); + + //XML缂栫爜 + private static final String XML_CHARSET = "UTF-8"; + //榛樿BUFSIZE + private static final int DEFAULT_BUFSIZE = 8 * 1024; + + public CustomLicenseManager() { + + } + + public CustomLicenseManager(LicenseParam param) { + super(param); + } + + /** + * 澶嶅啓create鏂规硶 + */ + @Override + protected synchronized byte[] create( + LicenseContent content, + LicenseNotary notary) + throws Exception { + initialize(content); + this.validateCreate(content); + final GenericCertificate certificate = notary.sign(content); + return getPrivacyGuard().cert2key(certificate); + } + + /** + * 澶嶅啓install鏂规硶锛屽叾涓璿alidate鏂规硶璋冪敤鏈被涓殑validate鏂规硶锛屾牎楠孖P鍦板潃銆丮ac鍦板潃绛夊叾浠栦俊鎭� + */ + @Override + protected synchronized LicenseContent install( + final byte[] key, + final LicenseNotary notary) + throws Exception { + final GenericCertificate certificate = getPrivacyGuard().key2cert(key); + + notary.verify(certificate); + final LicenseContent content = (LicenseContent)this.load(certificate.getEncoded()); + this.validate(content); + setLicenseKey(key); + setCertificate(certificate); + + return content; + } + + /** + * 澶嶅啓verify鏂规硶锛岃皟鐢ㄦ湰绫讳腑鐨剉alidate鏂规硶锛屾牎楠孖P鍦板潃銆丮ac鍦板潃绛夊叾浠栦俊鎭� + */ + @Override + protected synchronized LicenseContent verify(final LicenseNotary notary) + throws Exception { + GenericCertificate certificate = getCertificate(); + + // Load license key from preferences, + final byte[] key = getLicenseKey(); + if (null == key){ + throw new NoLicenseInstalledException(getLicenseParam().getSubject()); + } + + certificate = getPrivacyGuard().key2cert(key); + notary.verify(certificate); + final LicenseContent content = (LicenseContent)this.load(certificate.getEncoded()); + this.validate(content); + setCertificate(certificate); + + return content; + } + + /** + * 鏍¢獙鐢熸垚璇佷功鐨勫弬鏁颁俊鎭� + */ + protected synchronized void validateCreate(final LicenseContent content) + throws LicenseContentException { + final LicenseParam param = getLicenseParam(); + + final Date now = new Date(); + final Date notBefore = content.getNotBefore(); + final Date notAfter = content.getNotAfter(); + if (null != notAfter && now.after(notAfter)){ + throw new LicenseContentException("璇佷功澶辨晥鏃堕棿涓嶈兘鏃╀簬褰撳墠鏃堕棿"); + } + if (null != notBefore && null != notAfter && notAfter.before(notBefore)){ + throw new LicenseContentException("璇佷功鐢熸晥鏃堕棿涓嶈兘鏅氫簬璇佷功澶辨晥鏃堕棿"); + } + final String consumerType = content.getConsumerType(); + if (null == consumerType){ + throw new LicenseContentException("鐢ㄦ埛绫诲瀷涓嶈兘涓虹┖"); + } + } + + + /** + * 澶嶅啓validate鏂规硶锛屽鍔營P鍦板潃銆丮ac鍦板潃绛夊叾浠栦俊鎭牎楠� + */ + @Override + protected synchronized void validate(final LicenseContent content) + throws LicenseContentException { + //1. 棣栧厛璋冪敤鐖剁被鐨剉alidate鏂规硶 + super.validate(content); + + //2. 鐒跺悗鏍¢獙鑷畾涔夌殑License鍙傛暟 + //License涓彲琚厑璁哥殑鍙傛暟淇℃伅 + LicenseCheck expectedCheckModel = (LicenseCheck) content.getExtra(); + //褰撳墠鏈嶅姟鍣ㄧ湡瀹炵殑鍙傛暟淇℃伅 + LicenseCheck serverCheckModel = getServerInfos(); + + if(expectedCheckModel != null && serverCheckModel != null){ + //鏍¢獙IP鍦板潃 + if(!checkIpAddress(expectedCheckModel.getIpAddress(),serverCheckModel.getIpAddress())){ + throw new LicenseContentException("褰撳墠鏈嶅姟鍣ㄧ殑IP娌″湪鎺堟潈鑼冨洿鍐�"); + } + + //鏍¢獙Mac鍦板潃 + if(!checkIpAddress(expectedCheckModel.getMacAddress(),serverCheckModel.getMacAddress())){ + throw new LicenseContentException("褰撳墠鏈嶅姟鍣ㄧ殑Mac鍦板潃娌″湪鎺堟潈鑼冨洿鍐�"); + } + + //鏍¢獙涓绘澘搴忓垪鍙� + if(!checkSerial(expectedCheckModel.getMainBoardSerial(),serverCheckModel.getMainBoardSerial())){ + throw new LicenseContentException("褰撳墠鏈嶅姟鍣ㄧ殑涓绘澘搴忓垪鍙锋病鍦ㄦ巿鏉冭寖鍥村唴"); + } + + //鏍¢獙CPU搴忓垪鍙� + if(!checkSerial(expectedCheckModel.getCpuSerial(),serverCheckModel.getCpuSerial())){ + throw new LicenseContentException("褰撳墠鏈嶅姟鍣ㄧ殑CPU搴忓垪鍙锋病鍦ㄦ巿鏉冭寖鍥村唴"); + } + }else{ + throw new LicenseContentException("涓嶈兘鑾峰彇鏈嶅姟鍣ㄧ‖浠朵俊鎭�"); + } + } + + + /** + * 閲嶅啓XMLDecoder瑙f瀽XML + */ + private Object load(String encoded){ + BufferedInputStream inputStream = null; + XMLDecoder decoder = null; + try { + inputStream = new BufferedInputStream(new ByteArrayInputStream(encoded.getBytes(XML_CHARSET))); + + decoder = new XMLDecoder(new BufferedInputStream(inputStream, DEFAULT_BUFSIZE),null,null); + + return decoder.readObject(); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } finally { + try { + if(decoder != null){ + decoder.close(); + } + if(inputStream != null){ + inputStream.close(); + } + } catch (Exception e) { + logger.error("XMLDecoder瑙f瀽XML澶辫触",e); + } + } + + return null; + } + + /** + * 鑾峰彇褰撳墠鏈嶅姟鍣ㄩ渶瑕侀澶栨牎楠岀殑License鍙傛暟 + */ + private LicenseCheck getServerInfos(){ + //鎿嶄綔绯荤粺绫诲瀷 + String osName = System.getProperty("os.name").toLowerCase(); + AbstractServerInfos abstractServerInfos = null; + + //鏍规嵁涓嶅悓鎿嶄綔绯荤粺绫诲瀷閫夋嫨涓嶅悓鐨勬暟鎹幏鍙栨柟娉� + if (osName.startsWith("windows")) { + abstractServerInfos = new WindowsServerInfos(); + } else if (osName.startsWith("linux")) { + abstractServerInfos = new LinuxServerInfos(); + }else{//鍏朵粬鏈嶅姟鍣ㄧ被鍨� + abstractServerInfos = new WindowsServerInfos(); + } + + return abstractServerInfos.getServerInfos(); + } + + /** + * 鏍¢獙褰撳墠鏈嶅姟鍣ㄧ殑IP/Mac鍦板潃鏄惁鍦ㄥ彲琚厑璁哥殑IP鑼冨洿鍐�<br/> + * 濡傛灉瀛樺湪IP鍦ㄥ彲琚厑璁哥殑IP/Mac鍦板潃鑼冨洿鍐咃紝鍒欒繑鍥瀟rue + */ + private boolean checkIpAddress(List<String> expectedList,List<String> serverList){ + if(expectedList != null && expectedList.size() > 0){ + if(serverList != null && serverList.size() > 0){ + for(String expected : expectedList){ + if(serverList.contains(expected.trim())){ + return true; + } + } + } + + return false; + }else { + return true; + } + } + + /** + * 鏍¢獙褰撳墠鏈嶅姟鍣ㄧ‖浠讹紙涓绘澘銆丆PU绛夛級搴忓垪鍙锋槸鍚﹀湪鍙厑璁歌寖鍥村唴 + */ + private boolean checkSerial(String expectedSerial,String serverSerial){ + if(!Cools.isEmpty(expectedSerial)){ + if(!Cools.isEmpty(serverSerial)){ + if(expectedSerial.equals(serverSerial)){ + return true; + } + } + return false; + }else{ + return true; + } + } + +} \ No newline at end of file diff --git a/src/main/java/com/zy/system/entity/license/LicenseCheck.java b/src/main/java/com/zy/system/entity/license/LicenseCheck.java new file mode 100644 index 0000000..660f818 --- /dev/null +++ b/src/main/java/com/zy/system/entity/license/LicenseCheck.java @@ -0,0 +1,45 @@ +package com.zy.system.entity.license; + +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * 鑷畾涔夐渶瑕佹牎楠岀殑License鍙傛暟 + */ +@Data +public class LicenseCheck implements Serializable { + + private static final long serialVersionUID = 8600137500316662317L; + /** + * 鍙鍏佽鐨処P鍦板潃 + */ + private List<String> ipAddress; + + /** + * 鍙鍏佽鐨凪AC鍦板潃 + */ + private List<String> macAddress; + + /** + * 鍙鍏佽鐨凜PU搴忓垪鍙� + */ + private String cpuSerial; + + /** + * 鍙鍏佽鐨勪富鏉垮簭鍒楀彿 + */ + private String mainBoardSerial; + + @Override + public String toString() { + return "LicenseCheckModel{" + + "ipAddress=" + ipAddress + + ", macAddress=" + macAddress + + ", cpuSerial='" + cpuSerial + '\'' + + ", mainBoardSerial='" + mainBoardSerial + '\'' + + '}'; + } + +} diff --git a/src/main/java/com/zy/system/entity/license/LicenseCheckListener.java b/src/main/java/com/zy/system/entity/license/LicenseCheckListener.java new file mode 100644 index 0000000..cf79568 --- /dev/null +++ b/src/main/java/com/zy/system/entity/license/LicenseCheckListener.java @@ -0,0 +1,122 @@ +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; +import org.apache.logging.log4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ContextRefreshedEvent; +import org.springframework.stereotype.Component; + +import java.util.Date; + +/** + * 鍦ㄩ」鐩惎鍔ㄦ椂瀹夎璇佷功 + */ +@Component +public class LicenseCheckListener implements ApplicationListener<ContextRefreshedEvent> { + private static Logger logger = LogManager.getLogger(LicenseCheckListener.class); + + /** + * 璇佷功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 LicenseTimer licenseTimer; + @Autowired + private LicenseInfosService licenseInfosService; + + @Override + public void onApplicationEvent(ContextRefreshedEvent event) { + //root application context 娌℃湁parent + ApplicationContext context = event.getApplicationContext().getParent(); + if(context == null){ + loadLicense(); + } + } + + //鍔犺浇璇佷功 + public boolean loadLicense() { + if(!Cools.isEmpty(licensePath)){ + logger.info("++++++++ 寮�濮嬪姞杞借鍙瘉 ++++++++"); + + try { + licenseTimer.getRemoteLicense(); + } catch (Exception e) { + } + + try { + LicenseVerifyParam param = new LicenseVerifyParam(); + param.setSubject(subject); + param.setPublicAlias(publicAlias); + param.setStorePass(storePass); + param.setLicensePath(licensePath); + param.setPublicKeysStorePath(publicKeysStorePath); + + LicenseVerify licenseVerify = new LicenseVerify(); + + LicenseInfos latestLicense = licenseInfosService.getLatestLicense(); + if (latestLicense == null) { + logger.info("璁稿彲璇佷笉瀛樺湪"); + return false; + } + + //瀹夎璇佷功 + LicenseContent install = licenseVerify.install(param, latestLicense.getLicense()); + + logger.info("++++++++ 璁稿彲璇佸姞杞界粨鏉� ++++++++"); + + 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) { + e.printStackTrace(); + return false; + } + } + licenseTimer.setSystemSupport(false); + return false; + } +} \ No newline at end of file diff --git a/src/main/java/com/zy/system/entity/license/LicenseCreator.java b/src/main/java/com/zy/system/entity/license/LicenseCreator.java new file mode 100644 index 0000000..01f2ad1 --- /dev/null +++ b/src/main/java/com/zy/system/entity/license/LicenseCreator.java @@ -0,0 +1,86 @@ +package com.zy.system.entity.license; + +import de.schlichtherle.license.*; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import javax.security.auth.x500.X500Principal; +import java.io.File; +import java.text.MessageFormat; +import java.util.prefs.Preferences; + +/** + * License鐢熸垚绫� + */ +public class LicenseCreator { + private static Logger logger = LogManager.getLogger(LicenseCreator.class); + private final static X500Principal DEFAULT_HOLDER_AND_ISSUER = new X500Principal("CN=localhost, OU=localhost, O=localhost, L=SH, ST=SH, C=CN"); + private LicenseCreatorParam param; + + public LicenseCreator(LicenseCreatorParam param) { + this.param = param; + } + + /** + * 鐢熸垚License璇佷功 + */ + public boolean generateLicense(){ + try { + LicenseManager licenseManager = new CustomLicenseManager(initLicenseParam()); + LicenseContent licenseContent = initLicenseContent(); + + licenseManager.store(licenseContent,new File(param.getLicensePath())); + + return true; + }catch (Exception e){ + logger.error(MessageFormat.format("璇佷功鐢熸垚澶辫触锛歿0}",param),e); + return false; + } + } + + /** + * 鍒濆鍖栬瘉涔︾敓鎴愬弬鏁� + */ + private LicenseParam initLicenseParam(){ + Preferences preferences = Preferences.userNodeForPackage(LicenseCreator.class); + + //璁剧疆瀵硅瘉涔﹀唴瀹瑰姞瀵嗙殑绉橀挜 + CipherParam cipherParam = new DefaultCipherParam(param.getStorePass()); + + KeyStoreParam privateStoreParam = new CustomKeyStoreParam(LicenseCreator.class + ,param.getPrivateKeysStorePath() + ,param.getPrivateAlias() + ,param.getStorePass() + ,param.getKeyPass()); + + LicenseParam licenseParam = new DefaultLicenseParam(param.getSubject() + ,preferences + ,privateStoreParam + ,cipherParam); + + return licenseParam; + } + + /** + * 璁剧疆璇佷功鐢熸垚姝f枃淇℃伅 + */ + private LicenseContent initLicenseContent(){ + LicenseContent licenseContent = new LicenseContent(); + licenseContent.setHolder(DEFAULT_HOLDER_AND_ISSUER); + licenseContent.setIssuer(DEFAULT_HOLDER_AND_ISSUER); + + licenseContent.setSubject(param.getSubject()); + licenseContent.setIssued(param.getIssuedTime()); + licenseContent.setNotBefore(param.getIssuedTime()); + licenseContent.setNotAfter(param.getExpiryTime()); + licenseContent.setConsumerType(param.getConsumerType()); + licenseContent.setConsumerAmount(param.getConsumerAmount()); + licenseContent.setInfo(param.getDescription()); + + //鎵╁睍鏍¢獙鏈嶅姟鍣ㄧ‖浠朵俊鎭� + licenseContent.setExtra(param.getLicenseCheck()); + + return licenseContent; + } + +} \ No newline at end of file diff --git a/src/main/java/com/zy/system/entity/license/LicenseCreatorParam.java b/src/main/java/com/zy/system/entity/license/LicenseCreatorParam.java new file mode 100644 index 0000000..5a3915d --- /dev/null +++ b/src/main/java/com/zy/system/entity/license/LicenseCreatorParam.java @@ -0,0 +1,96 @@ +package com.zy.system.entity.license; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * License鐢熸垚绫婚渶瑕佺殑鍙傛暟 + */ +@Data +public class LicenseCreatorParam implements Serializable { + + private static final long serialVersionUID = -7793154252684580872L; + /** + * 璇佷功subject + */ + private String subject; + + /** + * 瀵嗛挜鍒О + */ + private String privateAlias; + + /** + * 瀵嗛挜瀵嗙爜锛堥渶瑕佸Ε鍠勪繚绠★紝涓嶈兘璁╀娇鐢ㄨ�呯煡閬擄級 + */ + private String keyPass; + + /** + * 璁块棶绉橀挜搴撶殑瀵嗙爜 + */ + private String storePass; + + /** + * 璇佷功鐢熸垚璺緞 + */ + private String licensePath; + + /** + * 瀵嗛挜搴撳瓨鍌ㄨ矾寰� + */ + private String privateKeysStorePath; + + /** + * 璇佷功鐢熸晥鏃堕棿 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date issuedTime = new Date(); + + /** + * 璇佷功澶辨晥鏃堕棿 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date expiryTime; + + /** + * 鐢ㄦ埛绫诲瀷 + */ + private String consumerType = "user"; + + /** + * 鐢ㄦ埛鏁伴噺 + */ + private Integer consumerAmount = 1; + + /** + * 鎻忚堪淇℃伅 + */ + private String description = ""; + + /** + * 棰濆鐨勬湇鍔″櫒纭欢鏍¢獙淇℃伅 + */ + private LicenseCheck licenseCheck; + + @Override + public String toString() { + return "LicenseCreatorParam{" + + "subject='" + subject + '\'' + + ", privateAlias='" + privateAlias + '\'' + + ", keyPass='" + keyPass + '\'' + + ", storePass='" + storePass + '\'' + + ", licensePath='" + licensePath + '\'' + + ", privateKeysStorePath='" + privateKeysStorePath + '\'' + + ", issuedTime=" + issuedTime + + ", expiryTime=" + expiryTime + + ", consumerType='" + consumerType + '\'' + + ", consumerAmount=" + consumerAmount + + ", description='" + description + '\'' + + ", licenseCheck=" + licenseCheck + + '}'; + } + +} diff --git a/src/main/java/com/zy/system/entity/license/LicenseManagerHolder.java b/src/main/java/com/zy/system/entity/license/LicenseManagerHolder.java new file mode 100644 index 0000000..64c6f39 --- /dev/null +++ b/src/main/java/com/zy/system/entity/license/LicenseManagerHolder.java @@ -0,0 +1,22 @@ +package com.zy.system.entity.license; + +import de.schlichtherle.license.LicenseManager; +import de.schlichtherle.license.LicenseParam; + +public class LicenseManagerHolder { + + private static volatile LicenseManager LICENSE_MANAGER; + + public static LicenseManager getInstance(LicenseParam param) { + if (LICENSE_MANAGER == null) { + synchronized (LicenseManagerHolder.class) { + if (LICENSE_MANAGER == null) { + LICENSE_MANAGER = new CustomLicenseManager(param); + } + } + } + + return LICENSE_MANAGER; + } + +} \ No newline at end of file diff --git a/src/main/java/com/zy/system/entity/license/LicenseVerify.java b/src/main/java/com/zy/system/entity/license/LicenseVerify.java new file mode 100644 index 0000000..da239c0 --- /dev/null +++ b/src/main/java/com/zy/system/entity/license/LicenseVerify.java @@ -0,0 +1,126 @@ +package com.zy.system.entity.license; + +import de.schlichtherle.license.*; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.File; +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; + +/** + * License鏍¢獙绫� + */ +public class LicenseVerify { + private static Logger logger = LogManager.getLogger(LicenseVerify.class); + + /** + * 瀹夎License璇佷功 + */ + public synchronized LicenseContent install(LicenseVerifyParam param, String license) { + LicenseContent result = null; + DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + + //1. 瀹夎璇佷功 + try { + LicenseParam licenseParam = initLicenseParam(param); + LicenseManager licenseManager = LicenseManagerHolder.getInstance(licenseParam); + licenseManager.uninstall(); + + 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; + } + + /** + * 鏍¢獙License璇佷功 + */ + public boolean verify(){ + try { + LicenseManager licenseManager = LicenseManagerHolder.getInstance(null); + DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + + LicenseContent licenseContent = licenseManager.verify(); + logger.info(MessageFormat.format("璁稿彲璇佹牎楠岄�氳繃锛岃鍙瘉鏈夋晥鏈燂細{0} - {1}",format.format(licenseContent.getNotBefore()),format.format(licenseContent.getNotAfter()))); + return true; + }catch (Exception e){ + logger.error("璁稿彲璇佹牎楠屽け璐ワ紒",e); + return false; + } + } + + /** + * 鏍¢獙License璇佷功骞惰幏鍙栬瘉涔︿俊鎭� + */ + public LicenseContent getVerifyInfo(){ + LicenseManager licenseManager = LicenseManagerHolder.getInstance(null); + + //鏍¢獙璇佷功 + try { + LicenseContent licenseContent = licenseManager.verify(); + return licenseContent; + }catch (Exception e){ + logger.error("璁稿彲璇佹牎楠屽け璐ワ紒",e); + return null; + } + } + + /** + * 鍒濆鍖栬瘉涔︾敓鎴愬弬鏁� + * @param param License鏍¢獙绫婚渶瑕佺殑鍙傛暟 + * @return de.schlichtherle.license.LicenseParam + */ + private LicenseParam initLicenseParam(LicenseVerifyParam param){ + Preferences preferences = Preferences.userNodeForPackage(LicenseVerify.class); + + CipherParam cipherParam = new DefaultCipherParam(param.getStorePass()); + + KeyStoreParam publicStoreParam = new CustomKeyStoreParam(LicenseVerify.class + ,param.getPublicKeysStorePath() + ,param.getPublicAlias() + ,param.getStorePass() + ,null); + + return new DefaultLicenseParam(param.getSubject() + ,preferences + ,publicStoreParam + ,cipherParam); + } + + /** + * 灏咮ase64瀛楃涓茶浆鎹负涓存椂鏂囦欢 + * @param base64String Base64缂栫爜鐨勫瓧绗︿覆 + * @param filePrefix 鏂囦欢鍚嶅墠缂�锛堜緥濡� "license_"锛� + * @param fileSuffix 鏂囦欢鍚庣紑锛堜緥濡� ".lic"锛� + * @return 鐢熸垚鐨勪复鏃禙ile瀵硅薄锛堣嚜鍔ㄥ湪JVM閫�鍑烘椂鍒犻櫎锛� + * @throws IOException + */ + public File base64ToTempFile(String base64String, String filePrefix, String fileSuffix) + throws IOException { + // 瑙g爜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"); + } + +} \ No newline at end of file diff --git a/src/main/java/com/zy/system/entity/license/LicenseVerifyParam.java b/src/main/java/com/zy/system/entity/license/LicenseVerifyParam.java new file mode 100644 index 0000000..33806e5 --- /dev/null +++ b/src/main/java/com/zy/system/entity/license/LicenseVerifyParam.java @@ -0,0 +1,48 @@ +package com.zy.system.entity.license; + +import lombok.Data; + +/** + * 鏍¢獙绛惧悕鏂囦欢 + */ +@Data +public class LicenseVerifyParam { + + /** + * 璇佷功subject + */ + private String subject; + + /** + * 鍏挜鍒О + */ + private String publicAlias; + + /** + * 璁块棶鍏挜搴撶殑瀵嗙爜 + */ + private String storePass; + + /** + * 璇佷功鐢熸垚璺緞 + */ + private String licensePath; + + /** + * 瀵嗛挜搴撳瓨鍌ㄨ矾寰� + */ + private String publicKeysStorePath; + + public LicenseVerifyParam() { + + } + + public LicenseVerifyParam(String subject, String publicAlias, String storePass, String licensePath, String publicKeysStorePath) { + this.subject = subject; + this.publicAlias = publicAlias; + this.storePass = storePass; + this.licensePath = licensePath; + this.publicKeysStorePath = publicKeysStorePath; + } + +} diff --git a/src/main/java/com/zy/system/entity/license/LinuxServerInfos.java b/src/main/java/com/zy/system/entity/license/LinuxServerInfos.java new file mode 100644 index 0000000..0f40daf --- /dev/null +++ b/src/main/java/com/zy/system/entity/license/LinuxServerInfos.java @@ -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. 鑾峰彇鎵�鏈夌綉缁滄帴鍙g殑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; + } +} \ No newline at end of file diff --git a/src/main/java/com/zy/system/entity/license/WindowsServerInfos.java b/src/main/java/com/zy/system/entity/license/WindowsServerInfos.java new file mode 100644 index 0000000..c575e6d --- /dev/null +++ b/src/main/java/com/zy/system/entity/license/WindowsServerInfos.java @@ -0,0 +1,85 @@ +package com.zy.system.entity.license; + +import java.net.InetAddress; +import java.util.List; +import java.util.Scanner; +import java.util.stream.Collectors; + +/** + * 鐢ㄤ簬鑾峰彇瀹㈡埛Windows鏈嶅姟鍣ㄧ殑鍩烘湰淇℃伅 + */ +public class WindowsServerInfos 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. 鑾峰彇鎵�鏈夌綉缁滄帴鍙g殑Mac鍦板潃 + result = inetAddresses.stream().map(this::getMacByInetAddress).distinct().collect(Collectors.toList()); + } + + return result; + } + + @Override + protected String getCPUSerial() throws Exception { + //搴忓垪鍙� + String serialNumber = ""; + + //浣跨敤WMIC鑾峰彇CPU搴忓垪鍙� + Process process = Runtime.getRuntime().exec("wmic cpu get processorid"); + process.getOutputStream().close(); + Scanner scanner = new Scanner(process.getInputStream()); + + if(scanner.hasNext()){ + scanner.next(); + } + + if(scanner.hasNext()){ + serialNumber = scanner.next().trim(); + } + + scanner.close(); + return serialNumber; + } + + @Override + protected String getMainBoardSerial() throws Exception { + //搴忓垪鍙� + String serialNumber = ""; + + //浣跨敤WMIC鑾峰彇涓绘澘搴忓垪鍙� + Process process = Runtime.getRuntime().exec("wmic baseboard get serialnumber"); + process.getOutputStream().close(); + Scanner scanner = new Scanner(process.getInputStream()); + + if(scanner.hasNext()){ + scanner.next(); + } + + if(scanner.hasNext()){ + serialNumber = scanner.next().trim(); + } + + scanner.close(); + return serialNumber; + } +} \ No newline at end of file diff --git a/src/main/java/com/zy/system/mapper/LicenseInfosMapper.java b/src/main/java/com/zy/system/mapper/LicenseInfosMapper.java new file mode 100644 index 0000000..7a47079 --- /dev/null +++ b/src/main/java/com/zy/system/mapper/LicenseInfosMapper.java @@ -0,0 +1,14 @@ +package com.zy.system.mapper; + +import com.baomidou.mybatisplus.mapper.BaseMapper; +import com.zy.system.entity.LicenseInfos; +import org.apache.ibatis.annotations.Mapper; +import org.springframework.stereotype.Repository; + +@Mapper +@Repository +public interface LicenseInfosMapper extends BaseMapper<LicenseInfos> { + + LicenseInfos getLatestLicense(); + +} diff --git a/src/main/java/com/zy/system/service/LicenseInfosService.java b/src/main/java/com/zy/system/service/LicenseInfosService.java new file mode 100644 index 0000000..75fdaab --- /dev/null +++ b/src/main/java/com/zy/system/service/LicenseInfosService.java @@ -0,0 +1,10 @@ +package com.zy.system.service; + +import com.baomidou.mybatisplus.service.IService; +import com.zy.system.entity.LicenseInfos; + +public interface LicenseInfosService extends IService<LicenseInfos> { + + LicenseInfos getLatestLicense(); + +} diff --git a/src/main/java/com/zy/system/service/impl/LicenseInfosServiceImpl.java b/src/main/java/com/zy/system/service/impl/LicenseInfosServiceImpl.java new file mode 100644 index 0000000..491a6c2 --- /dev/null +++ b/src/main/java/com/zy/system/service/impl/LicenseInfosServiceImpl.java @@ -0,0 +1,16 @@ +package com.zy.system.service.impl; + +import com.baomidou.mybatisplus.service.impl.ServiceImpl; +import com.zy.system.entity.LicenseInfos; +import com.zy.system.mapper.LicenseInfosMapper; +import com.zy.system.service.LicenseInfosService; +import org.springframework.stereotype.Service; + +@Service("licenseInfosService") +public class LicenseInfosServiceImpl extends ServiceImpl<LicenseInfosMapper, LicenseInfos> implements LicenseInfosService { + + @Override + public LicenseInfos getLatestLicense() { + return this.baseMapper.getLatestLicense(); + } +} diff --git a/src/main/java/com/zy/system/timer/LicenseTimer.java b/src/main/java/com/zy/system/timer/LicenseTimer.java new file mode 100644 index 0000000..dc49eb7 --- /dev/null +++ b/src/main/java/com/zy/system/timer/LicenseTimer.java @@ -0,0 +1,162 @@ +package com.zy.system.timer; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +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 { + + private static boolean SYSTEM_SUPPORT = false;//绯荤粺婵�娲荤姸鎬侊紝榛樿鍏抽棴 + + 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() { + 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(); + //瀹夎璇佷功 + 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() { + return SYSTEM_SUPPORT; + } + + public void setSystemSupport(boolean systemSupport) { + SYSTEM_SUPPORT = systemSupport; + } + + public int getLicenseDays() { + return LICENSE_DAYS; + } + + public void setLicenseDays(int licenseDays) { + LICENSE_DAYS = licenseDays; + } + +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index a4175b0..4d337f9 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -48,6 +48,14 @@ swagger: enable: false +#License鐩稿叧閰嶇疆 +license: + subject: mdqdasrs + publicAlias: publicCert + storePass: public_zhongyang_123456789 + licensePath: license.lic + publicKeysStorePath: publicCerts.keystore + # 涓嬩綅鏈洪厤缃� wcs-slave: # 鍙屾繁 diff --git a/src/main/resources/mapper/LicenseInfosMapper.xml b/src/main/resources/mapper/LicenseInfosMapper.xml new file mode 100644 index 0000000..368c596 --- /dev/null +++ b/src/main/resources/mapper/LicenseInfosMapper.xml @@ -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 dbo.sys_license_infos order by create_time desc + </select> + +</mapper> diff --git a/src/main/resources/publicCerts.keystore b/src/main/resources/publicCerts.keystore new file mode 100644 index 0000000..382a874 --- /dev/null +++ b/src/main/resources/publicCerts.keystore Binary files differ -- Gitblit v1.9.1