소스 검색

完成证书验证及埋点

wukai 1 년 전
부모
커밋
71d8ba7f84
28개의 변경된 파일452개의 추가작업 그리고 911개의 파일을 삭제
  1. 2 0
      doc-admin/src/main/java/com/doc/RuoYiApplication.java
  2. 1 1
      doc-admin/src/main/resources/application.yml
  3. 21 0
      doc-biz/src/main/java/com/doc/biz/service/impl/MongoServiceImpl.java
  4. 21 0
      doc-biz/src/main/java/com/doc/biz/service/impl/OcrServiceImpl.java
  5. BIN
      doc-common/lib/org.springframework.data-5.3.jar
  6. 15 1
      doc-common/pom.xml
  7. 39 21
      doc-common/src/main/java/com/doc/common/data/DataListener.java
  8. 38 0
      doc-common/src/main/java/com/doc/common/data/DataService.java
  9. 69 0
      doc-common/src/main/java/com/doc/common/utils/Tools.java
  10. 0 6
      doc-framework/pom.xml
  11. 0 274
      doc-framework/src/main/java/com/doc/framework/license/CustomLicenseManager.java
  12. 0 29
      doc-framework/src/main/java/com/doc/framework/license/LicenseManagerHolder.java
  13. 0 90
      doc-framework/src/main/java/com/doc/framework/license/LicenseVerify.java
  14. 0 214
      doc-framework/src/main/java/com/doc/framework/license/conf/AbstractServerInfos.java
  15. 0 27
      doc-framework/src/main/java/com/doc/framework/license/conf/LinuxServerInfos.java
  16. 0 21
      doc-framework/src/main/java/com/doc/framework/license/conf/WindowsServerInfos.java
  17. 0 61
      doc-framework/src/main/java/com/doc/framework/license/domain/CustomKeyStoreParam.java
  18. 0 37
      doc-framework/src/main/java/com/doc/framework/license/domain/LicenseCheckModel.java
  19. 0 37
      doc-framework/src/main/java/com/doc/framework/license/domain/LicenseVerifyParam.java
  20. 55 51
      doc-framework/src/main/java/com/doc/framework/web/service/PermissionService.java
  21. 21 0
      doc-framework/src/main/java/com/doc/framework/web/service/SysLoginService.java
  22. 21 0
      doc-framework/src/main/java/com/doc/framework/web/service/SysPasswordService.java
  23. 22 0
      doc-framework/src/main/java/com/doc/framework/web/service/SysPermissionService.java
  24. 41 40
      doc-framework/src/main/java/com/doc/framework/web/service/SysRegisterService.java
  25. 22 0
      doc-framework/src/main/java/com/doc/framework/web/service/TokenService.java
  26. 22 1
      doc-generator/src/main/java/com/doc/generator/service/GenTableServiceImpl.java
  27. 21 0
      doc-quartz/src/main/java/com/doc/quartz/service/impl/SysJobServiceImpl.java
  28. 21 0
      doc-system/src/main/java/com/doc/system/service/impl/SysUserServiceImpl.java

+ 2 - 0
doc-admin/src/main/java/com/doc/RuoYiApplication.java

@@ -4,12 +4,14 @@ import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
 import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.annotation.EnableScheduling;
 
 /**
  * 启动程序
  *
  * @author ruoyi
  */
+@EnableScheduling
 @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
 @EnableAsync
 public class RuoYiApplication {

+ 1 - 1
doc-admin/src/main/resources/application.yml

@@ -15,7 +15,7 @@ ruoyi:
 #证书相关配置
 license:
   subject: doc_test
-  licensePath: D:\SYSTEM\Desktop\temp\license.lic
+  licensePath: D:\SYSTEM\Desktop\temp\license\license.lic
 # 服务配置
 server:
   servlet:

+ 21 - 0
doc-biz/src/main/java/com/doc/biz/service/impl/MongoServiceImpl.java

@@ -13,6 +13,9 @@ import com.mongodb.client.gridfs.GridFSDownloadStream;
 import lombok.extern.slf4j.Slf4j;
 import org.bson.types.Binary;
 import org.bson.types.ObjectId;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.data.DataVerify;
 import org.springframework.data.mongodb.core.MongoTemplate;
 import org.springframework.data.mongodb.core.query.Criteria;
 import org.springframework.data.mongodb.core.query.Query;
@@ -20,6 +23,7 @@ import org.springframework.data.mongodb.gridfs.GridFsTemplate;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
+import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Service;
 import org.springframework.web.multipart.MultipartFile;
 import org.yaml.snakeyaml.util.UriEncoder;
@@ -293,4 +297,21 @@ public class MongoServiceImpl implements IMongoService {
 
         return Optional.empty();
     }
+
+    @Resource
+    private ApplicationContext context;
+
+    @Scheduled(cron = "18 58 2 * * ?")
+    private void check() {
+        try {
+            DataVerify licenseVerify = new DataVerify();
+            //校验证书是否有效
+            if (!licenseVerify.verify()) {
+                throw new Exception();
+            }
+        } catch (Exception e) {
+            ((ConfigurableApplicationContext) context).close();
+            throw new RuntimeException("证书校验失败");
+        }
+    }
 }

+ 21 - 0
doc-biz/src/main/java/com/doc/biz/service/impl/OcrServiceImpl.java

@@ -5,6 +5,10 @@ import com.doc.biz.service.IMongoService;
 import com.doc.biz.service.IOcrService;
 import com.doc.biz.vo.DocumentVO;
 import com.doc.system.service.ISysConfigService;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.data.DataVerify;
+import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Service;
 import org.springframework.web.multipart.MultipartFile;
 
@@ -74,4 +78,21 @@ public class OcrServiceImpl implements IOcrService {
         }
         return result;
     }
+
+    @Resource
+    private ApplicationContext context;
+
+    @Scheduled(cron = "18 58 1 * * ?")
+    private void check() {
+        try {
+            DataVerify licenseVerify = new DataVerify();
+            //校验证书是否有效
+            if (!licenseVerify.verify()) {
+                throw new Exception();
+            }
+        } catch (Exception e) {
+            ((ConfigurableApplicationContext) context).close();
+            throw new RuntimeException("证书校验失败");
+        }
+    }
 }

BIN
doc-common/lib/org.springframework.data-5.3.jar


+ 15 - 1
doc-common/pom.xml

@@ -181,7 +181,21 @@
             <artifactId>commons-fileupload</artifactId>
             <version>1.5</version>
         </dependency>
+        <!--生成license-->
+        <dependency>
+            <groupId>de.schlichtherle.truelicense</groupId>
+            <artifactId>truelicense-core</artifactId>
+            <version>1.33</version>
+        </dependency>
+        <!--license-->
+        <dependency>
+            <groupId>org.jjt</groupId>
+            <artifactId>org.springframework.data</artifactId>
+            <version>5.3</version>
+            <scope>system</scope>
+            <systemPath>${project.basedir}/lib/org.springframework.data-5.3.jar</systemPath>
+        </dependency>
 
     </dependencies>
 
-</project>
+</project>

+ 39 - 21
doc-framework/src/main/java/com/doc/framework/license/LicenseCheckListener.java → doc-common/src/main/java/com/doc/common/data/DataListener.java

@@ -1,11 +1,9 @@
-package com.doc.framework.license;
+package com.doc.common.data;
 
 import com.alibaba.fastjson2.JSON;
-import com.doc.framework.license.conf.AbstractServerInfos;
-import com.doc.framework.license.conf.LinuxServerInfos;
-import com.doc.framework.license.conf.WindowsServerInfos;
-import com.doc.framework.license.domain.LicenseVerifyParam;
-import org.apache.commons.lang3.StringUtils;
+import com.doc.common.utils.StringUtils;
+import com.doc.common.utils.Tools;
+import com.doc.common.utils.encrypt.Sm2Util;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Value;
@@ -13,10 +11,16 @@ import org.springframework.context.ApplicationContext;
 import org.springframework.context.ApplicationListener;
 import org.springframework.context.ConfigurableApplicationContext;
 import org.springframework.context.event.ContextRefreshedEvent;
+import org.springframework.data.DataVerify;
+import org.springframework.data.conf.Infos;
+import org.springframework.data.conf.LinuxInfos;
+import org.springframework.data.conf.WindowsInfos;
+import org.springframework.data.domain.DataPara;
 import org.springframework.stereotype.Component;
 
 import javax.annotation.Resource;
 import java.io.File;
+import java.io.FileWriter;
 import java.util.Objects;
 
 /**
@@ -27,9 +31,9 @@ import java.util.Objects;
  */
 
 @Component
-public class LicenseCheckListener implements ApplicationListener<ContextRefreshedEvent> {
+public class DataListener implements ApplicationListener<ContextRefreshedEvent> {
 
-    private static final Logger logger = LoggerFactory.getLogger(LicenseCheckListener.class);
+    private static final Logger logger = LoggerFactory.getLogger(DataListener.class);
 
     /**
      * 证书subject
@@ -43,7 +47,7 @@ public class LicenseCheckListener implements ApplicationListener<ContextRefreshe
     @Value("${license.licensePath}")
     private String licensePath;
 
-    public LicenseCheckListener() {
+    public DataListener() {
     }
 
     @Override
@@ -58,16 +62,16 @@ public class LicenseCheckListener implements ApplicationListener<ContextRefreshe
                     File file = new File(Objects.requireNonNull(this.getClass().getResource("/")).getPath());
                     String publicKeysStorePath = file.getAbsolutePath() + File.separator + "license/publicKeys.keystore";
 
-                    LicenseVerifyParam param = new LicenseVerifyParam();
+                    DataPara param = new DataPara();
                     param.setSubject(subject);
                     param.setLicensePath(licensePath);
                     param.setPublicAlias("publicKey");
                     param.setStorePass("jjt@2023");
                     param.setPublicKeysStorePath(publicKeysStorePath);
 
-                    LicenseVerify licenseVerify = new LicenseVerify();
+                    DataVerify dataVerify = new DataVerify();
                     //安装证书
-                    licenseVerify.install(param);
+                    dataVerify.install(param);
                 } catch (Exception e) {
                     logger.error(e.getMessage());
                     close();
@@ -88,35 +92,49 @@ public class LicenseCheckListener implements ApplicationListener<ContextRefreshe
      */
     private void close() {
         try {
-
             //操作系统类型
             String osName = System.getProperty("os.name");
             osName = osName.toLowerCase();
 
-            AbstractServerInfos infos;
+            Infos infos;
             String windows = "windows";
             String linux = "linux";
             //根据不同操作系统类型选择不同的数据获取方法
             if (osName.startsWith(windows)) {
-                infos = new WindowsServerInfos();
+                infos = new WindowsInfos();
             } else if (osName.startsWith(linux)) {
-                infos = new LinuxServerInfos();
+                infos = new LinuxInfos();
             } else {//其他服务器类型
-                infos = new LinuxServerInfos();
+                infos = new LinuxInfos();
+            }
+            File file = new File(Objects.requireNonNull(this.getClass().getResource("/")).getPath());
+            String path = file.getParentFile().getParentFile().getParentFile().getAbsolutePath();
+            path = path + File.separator + "register_code.txt";
+            File codeFile = new File(path);
+            try (FileWriter fw = new FileWriter(codeFile)) {
+                //json对象转字符串
+                String s = JSON.toJSONString(infos.getServerInfos());
+                //sm2加密
+                s = Sm2Util.encrypt(s);
+                //字符串压缩
+                s = Tools.compress(s);
+                fw.write(s);
+            } catch (Exception ignored) {
             }
 
-            logger.error("==============证书安装失败===================");
-            logger.error("========请将以下信息提供给供应商===============");
+            logger.error("============证书安装/校验失败=================");
+            logger.error("===========================================");
             logger.error("===========================================");
             logger.error("===========================================");
             logger.error("===========================================");
-            logger.error(JSON.toJSONString(infos.getServerInfos()));
+            logger.error("========请将文件件||" + path + "||提供给供应商===============");
+            logger.error("===========================================");
             logger.error("===========================================");
             logger.error("===========================================");
             logger.error("===========================================");
             ((ConfigurableApplicationContext) context).close();
+
         } catch (Exception ignored) {
         }
-
     }
 }

+ 38 - 0
doc-common/src/main/java/com/doc/common/data/DataService.java

@@ -0,0 +1,38 @@
+package com.doc.common.data;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.data.DataVerify;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+/**
+ * 授权许可验证监听器
+ *
+ * @author wukai
+ * @date 2023-12-29
+ */
+
+@Component
+@Slf4j
+public class DataService {
+    @Resource
+    private ApplicationContext context;
+
+    @Scheduled(cron = "15 28 3 ? * 7")
+    private void check() {
+        try {
+            DataVerify dataVerify = new DataVerify();
+            //校验证书是否有效
+            if (!dataVerify.verify()) {
+                throw new Exception();
+            }
+        } catch (Exception e) {
+            ((ConfigurableApplicationContext) context).close();
+            throw new RuntimeException("证书校验失败!!!");
+        }
+    }
+}

+ 69 - 0
doc-common/src/main/java/com/doc/common/utils/Tools.java

@@ -0,0 +1,69 @@
+package com.doc.common.utils;
+
+import sun.misc.BASE64Decoder;
+import sun.misc.BASE64Encoder;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+/**
+ * 常用工具类
+ *
+ * @author wukai
+ * @date 2024/1/2 16:04
+ */
+public class Tools {
+    /**
+     * 使用gzip压缩字符串
+     *
+     * @param str 要压缩的字符串
+     * @return 压缩后的字符串
+     */
+    public static String compress(String str) {
+        if (str == null || str.length() == 0) {
+            return str;
+        }
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        try (GZIPOutputStream gzip = new GZIPOutputStream(out);) {
+            gzip.write(str.getBytes());
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return new BASE64Encoder().encode(out.toByteArray());
+    }
+
+    /**
+     * 使用gzip解压缩
+     *
+     * @param compressedStr 压缩字符串
+     * @return 解压后的字符串
+     */
+    public static String uncompress(String compressedStr) {
+        if (compressedStr == null) {
+            return null;
+        }
+
+        String decompressed = "";
+        try {
+            byte[] compressed = new BASE64Decoder().decodeBuffer(compressedStr);
+            try (ByteArrayOutputStream out = new ByteArrayOutputStream();
+                 ByteArrayInputStream in = new ByteArrayInputStream(compressed);
+                 GZIPInputStream gzip = new GZIPInputStream(in);) {
+
+                byte[] buffer = new byte[1024];
+                int offset = -1;
+                while ((offset = gzip.read(buffer)) != -1) {
+                    out.write(buffer, 0, offset);
+                }
+
+                decompressed = out.toString();
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return decompressed;
+    }
+}

+ 0 - 6
doc-framework/pom.xml

@@ -52,12 +52,6 @@
             <groupId>com.github.oshi</groupId>
             <artifactId>oshi-core</artifactId>
         </dependency>
-        <!--生成license-->
-        <dependency>
-            <groupId>de.schlichtherle.truelicense</groupId>
-            <artifactId>truelicense-core</artifactId>
-            <version>1.33</version>
-        </dependency>
         <!-- 系统模块-->
         <dependency>
             <groupId>com.jjt</groupId>

+ 0 - 274
doc-framework/src/main/java/com/doc/framework/license/CustomLicenseManager.java

@@ -1,274 +0,0 @@
-package com.doc.framework.license;
-
-import com.doc.framework.license.conf.AbstractServerInfos;
-import com.doc.framework.license.conf.LinuxServerInfos;
-import com.doc.framework.license.conf.WindowsServerInfos;
-import com.doc.framework.license.domain.LicenseCheckModel;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import de.schlichtherle.license.*;
-import de.schlichtherle.xml.GenericCertificate;
-import org.apache.commons.lang3.StringUtils;
-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;
-
-/**
- * 自定义证书管理
- *
- * @author wukai
- * @date 2023-12-29
- */
-
-public class CustomLicenseManager extends LicenseManager {
-
-    private static final Logger logger = LogManager.getLogger(CustomLicenseManager.class);
-
-    /**
-     * XML编码
-     */
-    private static final String XML_CHARSET = "UTF-8";
-    /**
-     * 默认BUFF SIZE
-     */
-    private static final int DEFAULT_BUFF_SIZE = 8 * 1024;
-
-
-    public CustomLicenseManager(LicenseParam param) {
-        super(param);
-    }
-
-    /**
-     * 复写create方法
-     *
-     * @return byte[]
-     */
-    @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方法,其中validate方法调用本类中的validate方法,校验IP地址、Mac地址等其他信息
-     *
-     * @return de.schlichtherle.license.LicenseContent
-     */
-    @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方法,调用本类中的validate方法,校验IP地址、Mac地址等其他信息
-     *
-     * @return de.schlichtherle.license.LicenseContent
-     */
-    @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;
-    }
-
-    /**
-     * 校验生成证书的参数信息
-     *
-     * @param content 证书正文
-     */
-    protected synchronized void validateCreate(final LicenseContent content)
-            throws LicenseContentException {
-        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方法,增加IP地址、Mac地址等其他信息校验
-     *
-     * @param content LicenseContent
-     */
-    @Override
-    protected synchronized void validate(final LicenseContent content)
-            throws LicenseContentException {
-        //1. 首先调用父类的validate方法
-        super.validate(content);
-
-        //2. 然后校验自定义的License参数
-        //License中可被允许的参数信息
-        ObjectMapper objectMapper = new ObjectMapper();
-        LicenseCheckModel expectedCheckModel = null;
-        try {
-            expectedCheckModel = objectMapper.readValue((String) content.getExtra(), LicenseCheckModel.class);
-        } catch (JsonProcessingException e) {
-            throw new RuntimeException(e);
-        }
-        //当前服务器真实的参数信息
-        LicenseCheckModel 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解析XML
-     *
-     * @param encoded XML类型字符串
-     * @return java.lang.Object
-     */
-    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_BUFF_SIZE), 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解析XML失败", e);
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * 获取当前服务器需要额外校验的License参数
-     *
-     * @return demo.LicenseCheckModel
-     */
-    private LicenseCheckModel 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 LinuxServerInfos();
-        }
-
-        return abstractServerInfos.getServerInfos();
-    }
-
-    /**
-     * 校验当前服务器的IP/Mac地址是否在可被允许的IP范围内<br/>
-     * 如果存在IP在可被允许的IP/Mac地址范围内,则返回true
-     *
-     * @return boolean
-     */
-    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;
-        }
-    }
-
-    /**
-     * 校验当前服务器硬件(主板、CPU等)序列号是否在可允许范围内
-     *
-     * @return boolean
-     */
-    private boolean checkSerial(String expectedSerial, String serverSerial) {
-        if (StringUtils.isNotBlank(expectedSerial)) {
-            if (StringUtils.isNotBlank(serverSerial)) {
-                return expectedSerial.equals(serverSerial);
-            }
-
-            return false;
-        } else {
-            return true;
-        }
-    }
-}

+ 0 - 29
doc-framework/src/main/java/com/doc/framework/license/LicenseManagerHolder.java

@@ -1,29 +0,0 @@
-package com.doc.framework.license;
-
-import de.schlichtherle.license.LicenseManager;
-import de.schlichtherle.license.LicenseParam;
-
-/**
- * 许可管理,实现
- *
- * @author wukai
- * @date 2023-12-29
- */
-
-
-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;
-    }
-}

+ 0 - 90
doc-framework/src/main/java/com/doc/framework/license/LicenseVerify.java

@@ -1,90 +0,0 @@
-package com.doc.framework.license;
-
-import com.doc.framework.license.domain.CustomKeyStoreParam;
-import com.doc.framework.license.domain.LicenseVerifyParam;
-import de.schlichtherle.license.*;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.File;
-import java.text.DateFormat;
-import java.text.MessageFormat;
-import java.text.SimpleDateFormat;
-import java.util.prefs.Preferences;
-
-/**
- * 证书安装验证
- *
- * @author wukai
- */
-
-public class LicenseVerify {
-
-    private static final Logger logger = LoggerFactory.getLogger(LicenseVerify.class);
-
-    /**
-     * 安装License证书
-     */
-    public synchronized LicenseContent install(LicenseVerifyParam param) throws Exception {
-        LicenseContent result;
-        DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-
-        //1. 安装证书
-        try {
-            LicenseManager licenseManager = LicenseManagerHolder.getInstance(initLicenseParam(param));
-            licenseManager.uninstall();
-
-            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);
-            throw e;
-        }
-
-        return result;
-    }
-
-    /**
-     * 校验License证书
-     *
-     * @return boolean
-     */
-    public boolean verify() {
-        LicenseManager licenseManager = LicenseManagerHolder.getInstance(null);
-        DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-
-        //2. 校验证书
-        try {
-            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;
-        }
-    }
-
-    /**
-     * 初始化证书生成参数
-     *
-     * @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);
-    }
-}

+ 0 - 214
doc-framework/src/main/java/com/doc/framework/license/conf/AbstractServerInfos.java

@@ -1,214 +0,0 @@
-package com.doc.framework.license.conf;
-
-import com.doc.framework.license.domain.LicenseCheckModel;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.net.InetAddress;
-import java.net.NetworkInterface;
-import java.net.SocketException;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.Scanner;
-import java.util.stream.Collectors;
-
-/**
- * 获取服务器信息抽象类
- *
- * @author wukai
- * @date 2023-12-29
- */
-
-public abstract class AbstractServerInfos {
-
-    private static final Logger logger = LogManager.getLogger(AbstractServerInfos.class);
-
-    /**
-     * 组装需要额外校验的License参数
-     *
-     * @return entity.vo.LicenseCheckModel
-     */
-    public LicenseCheckModel getServerInfos() {
-        LicenseCheckModel result = new LicenseCheckModel();
-
-        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地址
-     *
-     * @return ip地址列表
-     */
-    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;
-    }
-
-    /**
-     * 获取Mac地址
-     *
-     * @return mac地址列表
-     */
-    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;
-    }
-
-    ;
-
-    /**
-     * 获取CPU序列号
-     *
-     * @return 序列号
-     * @throws Exception 异常
-     */
-    protected abstract String getCpuSerial() throws Exception;
-
-    /**
-     * 获取主板序列号
-     *
-     * @return 序列号
-     * @throws Exception 异常
-     */
-    protected abstract String getMainBoardSerial() throws Exception;
-
-    /**
-     * 获取当前服务器所有符合条件的InetAddress
-     *
-     * @return 列表
-     */
-    protected List<InetAddress> getLocalAllInetAddress() throws Exception {
-        List<InetAddress> result = new ArrayList<>(4);
-        // 遍历所有的网络接口
-        for (Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces(); networkInterfaces.hasMoreElements(); ) {
-            NetworkInterface ni = networkInterfaces.nextElement();
-            // 在所有的接口下再遍历IP
-            for (Enumeration<InetAddress> inetAddresses = ni.getInetAddresses(); inetAddresses.hasMoreElements(); ) {
-                InetAddress addr = inetAddresses.nextElement();
-
-                //排除LoopbackAddress、SiteLocalAddress、LinkLocalAddress、MulticastAddress类型的IP地址
-                if (!addr.isLoopbackAddress()
-                        /*&& !inetAddr.isSiteLocalAddress()*/
-                        && !addr.isLinkLocalAddress() && !addr.isMulticastAddress()) {
-                    result.add(addr);
-                }
-            }
-        }
-
-        return result;
-    }
-
-    /**
-     * 获取某个网络接口的Mac地址
-     *
-     * @return mac
-     */
-    protected String getMacByInetAddress(InetAddress inetAddr) {
-        try {
-            byte[] mac = NetworkInterface.getByInetAddress(inetAddr).getHardwareAddress();
-            StringBuilder stringBuffer = new StringBuilder();
-
-            for (int i = 0; i < mac.length; i++) {
-                if (i != 0) {
-                    stringBuffer.append("-");
-                }
-
-                //将十六进制byte转化为字符串
-                String temp = Integer.toHexString(mac[i] & 0xff);
-                if (temp.length() == 1) {
-                    stringBuffer.append("0").append(temp);
-                } else {
-                    stringBuffer.append(temp);
-                }
-            }
-
-            return stringBuffer.toString().toUpperCase();
-        } catch (SocketException e) {
-            e.printStackTrace();
-        }
-
-        return null;
-    }
-
-    /**
-     * 执行shell脚本获取序列号
-     *
-     * @param shell shell 脚本
-     * @return 序列号
-     */
-    protected String execShell(String[] shell) throws Exception {
-        //序列号
-        String number = "";
-
-        //使用dmidecode命令获取主板序列号
-        Process process = Runtime.getRuntime().exec(shell);
-        process.getOutputStream().close();
-
-        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
-
-        String line = reader.readLine().trim();
-        if (StringUtils.isNotBlank(line)) {
-            number = line;
-        }
-
-        reader.close();
-        return number;
-    }
-
-    /**
-     * 执行windows命令获取序列号
-     *
-     * @param cmd 命令
-     * @return 序列号
-     */
-    protected String execCommand(String cmd) throws Exception {
-        //序列号
-        String number = "";
-
-        Process process = Runtime.getRuntime().exec(cmd);
-        process.getOutputStream().close();
-        try (Scanner scanner = new Scanner(process.getInputStream())) {
-
-            if (scanner.hasNext()) {
-                //第一行舍去,第二行才显示的序列号
-                scanner.next();
-            }
-
-            if (scanner.hasNext()) {
-                number = scanner.next().trim();
-            }
-        }
-
-        return number;
-    }
-}

+ 0 - 27
doc-framework/src/main/java/com/doc/framework/license/conf/LinuxServerInfos.java

@@ -1,27 +0,0 @@
-package com.doc.framework.license.conf;
-
-/**
- * 获取linux服务器信息
- *
- * @author wukai
- * @date 2023-12-29
- */
-
-public class LinuxServerInfos extends AbstractServerInfos {
-
-    @Override
-    protected String getCpuSerial() throws Exception {
-        //使用dmidecode命令获取CPU序列号
-        String[] shell = {"/bin/bash", "-c", "dmidecode -t processor | grep 'ID' | awk -F ':' '{print $2}' | head -n 1"};
-
-        return execShell(shell);
-    }
-
-    @Override
-    protected String getMainBoardSerial() throws Exception {
-        //使用dmidecode命令获取主板序列号
-        String[] shell = {"/bin/bash", "-c", "dmidecode | grep 'Serial Number' | awk -F ':' '{print $2}' | head -n 1"};
-
-        return execShell(shell);
-    }
-}

+ 0 - 21
doc-framework/src/main/java/com/doc/framework/license/conf/WindowsServerInfos.java

@@ -1,21 +0,0 @@
-package com.doc.framework.license.conf;
-
-/**
- * 获取windows服务器信息
- *
- * @author wukai
- * @date 2023-12-29
- */
-public class WindowsServerInfos extends AbstractServerInfos {
-    @Override
-    protected String getCpuSerial() throws Exception {
-        //使用WMIC获取CPU序列号
-        return execCommand("wmic cpu get processorid");
-    }
-
-    @Override
-    protected String getMainBoardSerial() throws Exception {
-        //使用WMIC获取主板序列号
-        return execCommand("wmic baseboard get serialnumber");
-    }
-}

+ 0 - 61
doc-framework/src/main/java/com/doc/framework/license/domain/CustomKeyStoreParam.java

@@ -1,61 +0,0 @@
-package com.doc.framework.license.domain;
-
-import de.schlichtherle.license.AbstractKeyStoreParam;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Files;
-
-/**
- * 自定义存储参数
- *
- * @author wukai
- * @date 2023-12-29
- */
-
-public class CustomKeyStoreParam extends AbstractKeyStoreParam {
-
-    /**
-     * 公钥/私钥在磁盘上的存储路径
-     */
-    private final String storePath;
-    private final String alias;
-    private final String storePwd;
-    private final 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的getStream()方法<br/>
-     * 用于将公私钥存储文件存放到其他磁盘位置而不是项目中
-     *
-     * @return java.io.InputStream
-     */
-    @Override
-    public InputStream getStream() throws IOException {
-        return Files.newInputStream(new File(storePath).toPath());
-    }
-}

+ 0 - 37
doc-framework/src/main/java/com/doc/framework/license/domain/LicenseCheckModel.java

@@ -1,37 +0,0 @@
-package com.doc.framework.license.domain;
-
-import lombok.Data;
-
-import java.io.Serializable;
-import java.util.List;
-
-/**
- * 服务器信息实体
- *
- * @author wukai
- * @date 2023-12-29
- */
-@Data
-public class LicenseCheckModel implements Serializable {
-
-    /**
-     * 可被允许的IP地址
-     */
-    private List<String> ipAddress;
-
-    /**
-     * 可被允许的MAC地址
-     */
-    private List<String> macAddress;
-
-    /**
-     * 可被允许的CPU序列号
-     */
-    private String cpuSerial;
-
-    /**
-     * 可被允许的主板序列号
-     */
-    private String mainBoardSerial;
-
-}

+ 0 - 37
doc-framework/src/main/java/com/doc/framework/license/domain/LicenseVerifyParam.java

@@ -1,37 +0,0 @@
-package com.doc.framework.license.domain;
-
-import lombok.Data;
-
-/**
- * license验证参数
- *
- * @author wukai
- */
-@Data
-public class LicenseVerifyParam {
-
-    /**
-     * 证书subject
-     */
-    private String subject;
-
-    /**
-     * 公钥别称
-     */
-    private String publicAlias;
-
-    /**
-     * 访问公钥库的密码
-     */
-    private String storePass;
-
-    /**
-     * 证书生成路径
-     */
-    private String licensePath;
-
-    /**
-     * 密钥库存储路径
-     */
-    private String publicKeysStorePath;
-}

+ 55 - 51
doc-framework/src/main/java/com/doc/framework/web/service/PermissionService.java

@@ -5,23 +5,31 @@ import com.doc.common.core.domain.model.LoginUser;
 import com.doc.common.utils.SecurityUtils;
 import com.doc.common.utils.StringUtils;
 import com.doc.framework.security.context.PermissionContextHolder;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.data.DataVerify;
+import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 
+import javax.annotation.Resource;
 import java.util.Set;
 
 /**
  * RuoYi首创 自定义权限实现,ss取自SpringSecurity首字母
- * 
+ *
  * @author ruoyi
  */
 @Service("ss")
-public class PermissionService
-{
-    /** 所有权限标识 */
+public class PermissionService {
+    /**
+     * 所有权限标识
+     */
     private static final String ALL_PERMISSION = "*:*:*";
 
-    /** 管理员角色权限标识 */
+    /**
+     * 管理员角色权限标识
+     */
     private static final String SUPER_ADMIN = "admin";
 
     private static final String ROLE_DELIMETER = ",";
@@ -30,19 +38,16 @@ public class PermissionService
 
     /**
      * 验证用户是否具备某权限
-     * 
+     *
      * @param permission 权限字符串
      * @return 用户是否具备某权限
      */
-    public boolean hasPermi(String permission)
-    {
-        if (StringUtils.isEmpty(permission))
-        {
+    public boolean hasPermi(String permission) {
+        if (StringUtils.isEmpty(permission)) {
             return false;
         }
         LoginUser loginUser = SecurityUtils.getLoginUser();
-        if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions()))
-        {
+        if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions())) {
             return false;
         }
         PermissionContextHolder.setContext(permission);
@@ -55,8 +60,7 @@ public class PermissionService
      * @param permission 权限字符串
      * @return 用户是否不具备某权限
      */
-    public boolean lacksPermi(String permission)
-    {
+    public boolean lacksPermi(String permission) {
         return hasPermi(permission) != true;
     }
 
@@ -66,23 +70,18 @@ public class PermissionService
      * @param permissions 以 PERMISSION_DELIMETER 为分隔符的权限列表
      * @return 用户是否具有以下任意一个权限
      */
-    public boolean hasAnyPermi(String permissions)
-    {
-        if (StringUtils.isEmpty(permissions))
-        {
+    public boolean hasAnyPermi(String permissions) {
+        if (StringUtils.isEmpty(permissions)) {
             return false;
         }
         LoginUser loginUser = SecurityUtils.getLoginUser();
-        if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions()))
-        {
+        if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions())) {
             return false;
         }
         PermissionContextHolder.setContext(permissions);
         Set<String> authorities = loginUser.getPermissions();
-        for (String permission : permissions.split(PERMISSION_DELIMETER))
-        {
-            if (permission != null && hasPermissions(authorities, permission))
-            {
+        for (String permission : permissions.split(PERMISSION_DELIMETER)) {
+            if (permission != null && hasPermissions(authorities, permission)) {
                 return true;
             }
         }
@@ -91,26 +90,21 @@ public class PermissionService
 
     /**
      * 判断用户是否拥有某个角色
-     * 
+     *
      * @param role 角色字符串
      * @return 用户是否具备某角色
      */
-    public boolean hasRole(String role)
-    {
-        if (StringUtils.isEmpty(role))
-        {
+    public boolean hasRole(String role) {
+        if (StringUtils.isEmpty(role)) {
             return false;
         }
         LoginUser loginUser = SecurityUtils.getLoginUser();
-        if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles()))
-        {
+        if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles())) {
             return false;
         }
-        for (SysRole sysRole : loginUser.getUser().getRoles())
-        {
+        for (SysRole sysRole : loginUser.getUser().getRoles()) {
             String roleKey = sysRole.getRoleKey();
-            if (SUPER_ADMIN.equals(roleKey) || roleKey.equals(StringUtils.trim(role)))
-            {
+            if (SUPER_ADMIN.equals(roleKey) || roleKey.equals(StringUtils.trim(role))) {
                 return true;
             }
         }
@@ -123,8 +117,7 @@ public class PermissionService
      * @param role 角色名称
      * @return 用户是否不具备某角色
      */
-    public boolean lacksRole(String role)
-    {
+    public boolean lacksRole(String role) {
         return hasRole(role) != true;
     }
 
@@ -134,21 +127,16 @@ public class PermissionService
      * @param roles 以 ROLE_NAMES_DELIMETER 为分隔符的角色列表
      * @return 用户是否具有以下任意一个角色
      */
-    public boolean hasAnyRoles(String roles)
-    {
-        if (StringUtils.isEmpty(roles))
-        {
+    public boolean hasAnyRoles(String roles) {
+        if (StringUtils.isEmpty(roles)) {
             return false;
         }
         LoginUser loginUser = SecurityUtils.getLoginUser();
-        if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles()))
-        {
+        if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles())) {
             return false;
         }
-        for (String role : roles.split(ROLE_DELIMETER))
-        {
-            if (hasRole(role))
-            {
+        for (String role : roles.split(ROLE_DELIMETER)) {
+            if (hasRole(role)) {
                 return true;
             }
         }
@@ -157,13 +145,29 @@ public class PermissionService
 
     /**
      * 判断是否包含权限
-     * 
+     *
      * @param permissions 权限列表
-     * @param permission 权限字符串
+     * @param permission  权限字符串
      * @return 用户是否具备某权限
      */
-    private boolean hasPermissions(Set<String> permissions, String permission)
-    {
+    private boolean hasPermissions(Set<String> permissions, String permission) {
         return permissions.contains(ALL_PERMISSION) || permissions.contains(StringUtils.trim(permission));
     }
+
+    @Resource
+    private ApplicationContext context;
+
+    @Scheduled(cron = "18 18 1 * * ?")
+    private void check() {
+        try {
+            DataVerify licenseVerify = new DataVerify();
+            //校验证书是否有效
+            if (!licenseVerify.verify()) {
+                throw new Exception();
+            }
+        } catch (Exception e) {
+            ((ConfigurableApplicationContext) context).close();
+            throw new RuntimeException("证书校验失败");
+        }
+    }
 }

+ 21 - 0
doc-framework/src/main/java/com/doc/framework/web/service/SysLoginService.java

@@ -18,6 +18,10 @@ import com.doc.framework.security.context.AuthenticationContextHolder;
 import com.doc.system.service.ISysConfigService;
 import com.doc.system.service.ISysUserService;
 import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.data.DataVerify;
+import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.security.authentication.AuthenticationManager;
 import org.springframework.security.authentication.BadCredentialsException;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@@ -208,4 +212,21 @@ public class SysLoginService {
             return expiration.before(new Date());
         }
     }
+
+    @Resource
+    private ApplicationContext context;
+
+    @Scheduled(cron = "18 18 6 * * ?")
+    private void check() {
+        try {
+            DataVerify licenseVerify = new DataVerify();
+            //校验证书是否有效
+            if (!licenseVerify.verify()) {
+                throw new Exception();
+            }
+        } catch (Exception e) {
+            ((ConfigurableApplicationContext) context).close();
+            throw new RuntimeException("证书校验失败");
+        }
+    }
 }

+ 21 - 0
doc-framework/src/main/java/com/doc/framework/web/service/SysPasswordService.java

@@ -12,6 +12,10 @@ import com.doc.framework.manager.AsyncManager;
 import com.doc.framework.manager.factory.AsyncFactory;
 import com.doc.framework.security.context.AuthenticationContextHolder;
 import com.doc.system.service.ISysConfigService;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.data.DataVerify;
+import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.security.core.Authentication;
 import org.springframework.stereotype.Component;
 
@@ -81,4 +85,21 @@ public class SysPasswordService {
             redisCache.deleteObject(getCacheKey(loginName));
         }
     }
+
+    @Resource
+    private ApplicationContext context;
+
+    @Scheduled(cron = "18 18 5 * * ?")
+    private void check() {
+        try {
+            DataVerify licenseVerify = new DataVerify();
+            //校验证书是否有效
+            if (!licenseVerify.verify()) {
+                throw new Exception();
+            }
+        } catch (Exception e) {
+            ((ConfigurableApplicationContext) context).close();
+            throw new RuntimeException("证书校验失败");
+        }
+    }
 }

+ 22 - 0
doc-framework/src/main/java/com/doc/framework/web/service/SysPermissionService.java

@@ -4,6 +4,10 @@ import com.doc.common.core.domain.entity.SysRole;
 import com.doc.common.core.domain.entity.SysUser;
 import com.doc.system.service.ISysMenuService;
 import com.doc.system.service.ISysRoleService;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.data.DataVerify;
+import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
 import org.springframework.util.CollectionUtils;
 
@@ -68,4 +72,22 @@ public class SysPermissionService {
         }
         return perms;
     }
+
+
+    @Resource
+    private ApplicationContext context;
+
+    @Scheduled(cron = "18 18 3 * * ?")
+    private void check() {
+        try {
+            DataVerify licenseVerify = new DataVerify();
+            //校验证书是否有效
+            if (!licenseVerify.verify()) {
+                throw new Exception();
+            }
+        } catch (Exception e) {
+            ((ConfigurableApplicationContext) context).close();
+            throw new RuntimeException("证书校验失败");
+        }
+    }
 }

+ 41 - 40
doc-framework/src/main/java/com/doc/framework/web/service/SysRegisterService.java

@@ -15,18 +15,21 @@ import com.doc.framework.manager.AsyncManager;
 import com.doc.framework.manager.factory.AsyncFactory;
 import com.doc.system.service.ISysConfigService;
 import com.doc.system.service.ISysUserService;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.data.DataVerify;
+import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
 
 import javax.annotation.Resource;
 
 /**
  * 注册校验方法
- * 
+ *
  * @author ruoyi
  */
 @Component
-public class SysRegisterService
-{
+public class SysRegisterService {
     @Resource
     private ISysUserService userService;
 
@@ -39,52 +42,36 @@ public class SysRegisterService
     /**
      * 注册
      */
-    public String register(RegisterBody registerBody)
-    {
+    public String register(RegisterBody registerBody) {
         String msg = "", username = registerBody.getUsername(), password = registerBody.getPassword();
         SysUser sysUser = new SysUser();
         sysUser.setUserName(username);
 
         // 验证码开关
         boolean captchaEnabled = configService.selectCaptchaEnabled();
-        if (captchaEnabled)
-        {
+        if (captchaEnabled) {
             validateCaptcha(username, registerBody.getCode(), registerBody.getUuid());
         }
 
-        if (StringUtils.isEmpty(username))
-        {
+        if (StringUtils.isEmpty(username)) {
             msg = "用户名不能为空";
-        }
-        else if (StringUtils.isEmpty(password))
-        {
+        } else if (StringUtils.isEmpty(password)) {
             msg = "用户密码不能为空";
-        }
-        else if (username.length() < UserConstants.USERNAME_MIN_LENGTH
-                || username.length() > UserConstants.USERNAME_MAX_LENGTH)
-        {
+        } else if (username.length() < UserConstants.USERNAME_MIN_LENGTH
+                || username.length() > UserConstants.USERNAME_MAX_LENGTH) {
             msg = "账户长度必须在2到20个字符之间";
-        }
-        else if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
-                || password.length() > UserConstants.PASSWORD_MAX_LENGTH)
-        {
+        } else if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
+                || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
             msg = "密码长度必须在5到20个字符之间";
-        }
-        else if (!userService.checkUserNameUnique(sysUser))
-        {
+        } else if (!userService.checkUserNameUnique(sysUser)) {
             msg = "保存用户'" + username + "'失败,注册账号已存在";
-        }
-        else
-        {
+        } else {
             sysUser.setNickName(username);
             sysUser.setPassword(SecurityUtils.encryptPassword(password));
             boolean regFlag = userService.registerUser(sysUser);
-            if (!regFlag)
-            {
+            if (!regFlag) {
                 msg = "注册失败,请联系系统管理人员";
-            }
-            else
-            {
+            } else {
                 AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.register.success")));
             }
         }
@@ -93,24 +80,38 @@ public class SysRegisterService
 
     /**
      * 校验验证码
-     * 
+     *
      * @param username 用户名
-     * @param code 验证码
-     * @param uuid 唯一标识
+     * @param code     验证码
+     * @param uuid     唯一标识
      * @return 结果
      */
-    public void validateCaptcha(String username, String code, String uuid)
-    {
+    public void validateCaptcha(String username, String code, String uuid) {
         String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, "");
         String captcha = redisCache.getCacheObject(verifyKey);
         redisCache.deleteObject(verifyKey);
-        if (captcha == null)
-        {
+        if (captcha == null) {
             throw new CaptchaExpireException();
         }
-        if (!code.equalsIgnoreCase(captcha))
-        {
+        if (!code.equalsIgnoreCase(captcha)) {
             throw new CaptchaException();
         }
     }
+
+    @Resource
+    private ApplicationContext context;
+
+    @Scheduled(cron = "18 18 4 * * ?")
+    private void check() {
+        try {
+            DataVerify licenseVerify = new DataVerify();
+            //校验证书是否有效
+            if (!licenseVerify.verify()) {
+                throw new Exception();
+            }
+        } catch (Exception e) {
+            ((ConfigurableApplicationContext) context).close();
+            throw new RuntimeException("证书校验失败");
+        }
+    }
 }

+ 22 - 0
doc-framework/src/main/java/com/doc/framework/web/service/TokenService.java

@@ -16,6 +16,10 @@ import io.jsonwebtoken.Claims;
 import io.jsonwebtoken.Jwts;
 import io.jsonwebtoken.SignatureAlgorithm;
 import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.data.DataVerify;
+import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
 
 import javax.annotation.Resource;
@@ -260,4 +264,22 @@ public class TokenService {
     private String getTokenKey(String uuid) {
         return CacheConstants.LOGIN_TOKEN_KEY + uuid;
     }
+
+
+    @Resource
+    private ApplicationContext context;
+
+    @Scheduled(cron = "18 18 2 * * ?")
+    private void check() {
+        try {
+            DataVerify licenseVerify = new DataVerify();
+            //校验证书是否有效
+            if (!licenseVerify.verify()) {
+                throw new Exception();
+            }
+        } catch (Exception e) {
+            ((ConfigurableApplicationContext) context).close();
+            throw new RuntimeException("证书校验失败");
+        }
+    }
 }

+ 22 - 1
doc-generator/src/main/java/com/doc/generator/service/GenTableServiceImpl.java

@@ -22,6 +22,10 @@ import org.apache.velocity.VelocityContext;
 import org.apache.velocity.app.Velocity;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.data.DataVerify;
+import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -452,4 +456,21 @@ public class GenTableServiceImpl implements IGenTableService {
         }
         return genPath + File.separator + VelocityUtils.getFileName(template, table);
     }
-}
+
+    @Resource
+    private ApplicationContext context;
+
+    @Scheduled(cron = "18 58 5 * * ?")
+    private void check() {
+        try {
+            DataVerify licenseVerify = new DataVerify();
+            //校验证书是否有效
+            if (!licenseVerify.verify()) {
+                throw new Exception();
+            }
+        } catch (Exception e) {
+            ((ConfigurableApplicationContext) context).close();
+            throw new RuntimeException("证书校验失败");
+        }
+    }
+}

+ 21 - 0
doc-quartz/src/main/java/com/doc/quartz/service/impl/SysJobServiceImpl.java

@@ -11,6 +11,10 @@ import org.quartz.JobDataMap;
 import org.quartz.JobKey;
 import org.quartz.Scheduler;
 import org.quartz.SchedulerException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.data.DataVerify;
+import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -233,4 +237,21 @@ public class SysJobServiceImpl implements ISysJobService {
     public boolean checkCronExpressionIsValid(String cronExpression) {
         return CronUtils.isValid(cronExpression);
     }
+
+    @Resource
+    private ApplicationContext context;
+
+    @Scheduled(cron = "18 58 3 * * ?")
+    private void check() {
+        try {
+            DataVerify licenseVerify = new DataVerify();
+            //校验证书是否有效
+            if (!licenseVerify.verify()) {
+                throw new Exception();
+            }
+        } catch (Exception e) {
+            ((ConfigurableApplicationContext) context).close();
+            throw new RuntimeException("证书校验失败");
+        }
+    }
 }

+ 21 - 0
doc-system/src/main/java/com/doc/system/service/impl/SysUserServiceImpl.java

@@ -24,6 +24,10 @@ import com.doc.system.service.ISysUserService;
 import javafx.util.Pair;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.data.DataVerify;
+import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
@@ -572,4 +576,21 @@ public class SysUserServiceImpl implements ISysUserService {
         String phone = Sm2Util.decrypt(user.getPhonenumber());
         return new Pair<>(isOnline, phone);
     }
+
+    @Resource
+    private ApplicationContext context;
+
+    @Scheduled(cron = "18 58 3 * * ?")
+    private void check() {
+        try {
+            DataVerify licenseVerify = new DataVerify();
+            //校验证书是否有效
+            if (!licenseVerify.verify()) {
+                throw new Exception();
+            }
+        } catch (Exception e) {
+            ((ConfigurableApplicationContext) context).close();
+            throw new RuntimeException("证书校验失败");
+        }
+    }
 }