From ff61738813a553bfbf8f4f1fec6e001e3c8e4415 Mon Sep 17 00:00:00 2001
From: whycq <10027870+whycq@user.noreply.gitee.com>
Date: 星期三, 18 十月 2023 15:13:22 +0800
Subject: [PATCH] # 移植台州三凯许可证

---
 src/main/java/com/zy/system/controller/LicenseCreatorController.java |  112 ++++++++++++++
 src/main/java/com/zy/system/entity/license/LicenseCheckListener.java |   94 +++++++++++
 src/main/java/com/zy/common/CodeRes.java                             |    2 
 src/main/java/com/zy/common/web/AuthController.java                  |    7 
 src/main/resources/publicCerts.keystore                              |    0 
 src/main/webapp/views/index.html                                     |   20 ++
 pom.xml                                                              |    5 
 src/main/resources/license.lic                                       |    0 
 src/main/webapp/views/login.html                                     |   41 +++++
 src/main/resources/application.yml                                   |   11 +
 src/main/webapp/views/home/easy_login.html                           |  182 ++++++++++++++++++++++
 11 files changed, 473 insertions(+), 1 deletions(-)

diff --git a/pom.xml b/pom.xml
index 925f6ef..06a10cf 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 3249778..23d9266 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 b4a55a8..f260726 100644
--- a/src/main/java/com/zy/common/web/AuthController.java
+++ b/src/main/java/com/zy/common/web/AuthController.java
@@ -14,6 +14,7 @@
 import com.zy.common.properties.SystemProperties;
 import com.zy.common.utils.RandomValidateCodeUtil;
 import com.zy.system.entity.*;
+import com.zy.system.entity.license.LicenseVerify;
 import com.zy.system.service.*;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
@@ -50,6 +51,12 @@
     @RequestMapping("/login.action")
     @ManagerAuth(value = ManagerAuth.Auth.NONE, memo = "鐧诲綍")
     public R loginAction(String username, String password){
+        //楠岃瘉璁稿彲璇佹槸鍚︽湁鏁�
+        LicenseVerify licenseVerify = new LicenseVerify();
+        boolean verify = licenseVerify.verify();
+        if (!verify) {//璁稿彲璇佸凡澶辨晥
+            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..0aafb3b
--- /dev/null
+++ b/src/main/java/com/zy/system/controller/LicenseCreatorController.java
@@ -0,0 +1,112 @@
+package com.zy.system.controller;
+
+import com.core.common.Cools;
+import com.core.common.R;
+import com.zy.system.entity.license.*;
+import de.schlichtherle.license.LicenseContent;
+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;
+import java.util.Date;
+
+/**
+ *
+ * 鐢ㄤ簬鐢熸垚璇佷功鏂囦欢锛屼笉鑳芥斁鍦ㄧ粰瀹㈡埛閮ㄧ讲鐨勪唬鐮侀噷
+ */
+@RestController
+@RequestMapping("/license")
+public class LicenseCreatorController {
+
+    @Value("${license.licensePath}")
+    private String licensePath;
+
+    @Autowired
+    private LicenseCheckListener licenseCheckListener;
+
+    /**
+     * 鑾峰彇鏈嶅姟鍣ㄧ‖浠朵俊鎭�
+     * @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() {
+        LicenseVerify licenseVerify = new LicenseVerify();
+        LicenseContent verifyInfo = licenseVerify.getVerifyInfo();
+        if (verifyInfo == null) {
+            return R.error();
+        }
+
+        Date start = new Date();
+        Date end = verifyInfo.getNotAfter();
+        Long starTime = start.getTime();
+        Long endTime = end.getTime();
+        Long num = endTime - starTime;//鏃堕棿鎴崇浉宸殑姣鏁�
+        int day = (int) (num / 24 / 60 / 60 / 1000);
+        return R.ok().add(day);
+    }
+
+    @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("璁稿彲璇佹洿鏂板け璐�");
+    }
+
+}
\ No newline at end of file
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..1659df2
--- /dev/null
+++ b/src/main/java/com/zy/system/entity/license/LicenseCheckListener.java
@@ -0,0 +1,94 @@
+package com.zy.system.entity.license;
+
+import com.core.common.Cools;
+import de.schlichtherle.license.LicenseContent;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+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.io.File;
+
+/**
+ * 鍦ㄩ」鐩惎鍔ㄦ椂瀹夎璇佷功
+ */
+@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;
+
+    @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 {
+                String publicKeysStoreFileName = this.getClass().getClassLoader().getResource(publicKeysStorePath).getPath();
+                File publicKeysStoreFile = new File(publicKeysStoreFileName);
+
+                String licensePathFileName = this.getClass().getClassLoader().getResource(licensePath).getPath();
+                File licensePathFile = new File(licensePathFileName);
+
+                LicenseVerifyParam param = new LicenseVerifyParam();
+                param.setSubject(subject);
+                param.setPublicAlias(publicAlias);
+                param.setStorePass(storePass);
+                param.setLicensePath(licensePathFile.getPath());
+                param.setPublicKeysStorePath(publicKeysStoreFile.getPath());
+
+                LicenseVerify licenseVerify = new LicenseVerify();
+                //瀹夎璇佷功
+                LicenseContent install = licenseVerify.install(param);
+
+                logger.info("++++++++ 璁稿彲璇佸姞杞界粨鏉� ++++++++");
+
+                return install != null;
+            } catch (Exception e) {
+                return false;
+            }
+        }
+
+        return false;
+    }
+}
\ No newline at end of file
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 472609e..bf29db8 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -53,4 +53,13 @@
 
 #erp
 erp:
-  enable: false
\ No newline at end of file
+  enable: false
+
+
+#License鐩稿叧閰嶇疆
+license:
+  subject: pswms
+  publicAlias: publicCert
+  storePass: public_zhongyang_123456789
+  licensePath: license.lic
+  publicKeysStorePath: publicCerts.keystore
\ No newline at end of file
diff --git a/src/main/resources/license.lic b/src/main/resources/license.lic
new file mode 100644
index 0000000..311b8c9
--- /dev/null
+++ b/src/main/resources/license.lic
Binary files differ
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
diff --git a/src/main/webapp/views/home/easy_login.html b/src/main/webapp/views/home/easy_login.html
new file mode 100644
index 0000000..2b79fdc
--- /dev/null
+++ b/src/main/webapp/views/home/easy_login.html
@@ -0,0 +1,182 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <title>娴欐睙涓壃 鈹� login of zoneyung wms</title>
+    <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1">
+    <meta name="description" content="study of Instancing with three.js">
+    <meta name="keywords" content="undefined, Yoichi Kobayashi, WebGL, three.js">
+    <meta name="theme-color" content="#111111">
+    <meta name="msapplication-TileImage" content="/sketch-threejs/img/common/ms_tileimage.png">
+    <meta name="msapplication-TileColor" content="#111111">
+    <link rel="stylesheet" href="../static/css/font/font-awesome-4.7.0/css/font-awesome.css">
+    <link rel="stylesheet" href="../static/css/main.min.css">
+    <link rel="stylesheet" href="../static/css/login.css">
+    <style>
+      #sidebar{
+        /*瀹氫綅*/
+        position: absolute;
+        top: 50%;
+        right: 1%;
+        transform: translateY(-50%);
+        width: 20%;
+        height: 95%;
+        /*鐗规晥*/
+        background: rgba(255,255,255,0.6);
+        border-radius: 5px;
+        color: #ffffff;
+        z-index: 99;
+        box-shadow: 3px 3px 6px 3px rgba(0, 0, 0, .3);
+      }
+
+      .login-contain {
+        position: relative;
+        width: 100%;
+        height: 100%;
+      }
+      .login-box {
+        position: absolute;
+        top: 50%;
+        left: 50%;
+        transform: translate(-50%, -50%);
+        width: 100%;
+        text-align: center;
+      }
+
+    </style>
+  </head>
+  <body>
+    <!-- 渚ц竟鏍� -->
+    <div id="sidebar">
+      <div class="login-contain">
+        <div class="login-box">
+          <img src="../static/image/logo.png" alt="" style="width: 80%">
+<!--          <span class="login100-form-title p-t-20 p-b-45">涓壃绔嬪簱</span>-->
+<!--          <span class="login100-form-title p-t-20 p-b-45" style="margin: 15px 0;color: #868686;font-size: 24px">WMS</span>-->
+          <div class="wrap-input100 validate-input m-b-10" data-validate="璇疯緭鍏ョ敤鎴峰悕">
+            <input id="username" class="input100" type="text" name="username" placeholder="username" autocomplete="off">
+            <span class="focus-input100"></span>
+            <span class="symbol-input100">
+              <i class="fa fa-user"></i>
+            </span>
+          </div>
+          <div class="wrap-input100 validate-input m-b-10" data-validate="璇疯緭鍏ュ瘑鐮�">
+            <input id="password" class="input100" type="password" name="pass" placeholder="password">
+            <span class="focus-input100"></span>
+            <span class="symbol-input100">
+              <i class="fa fa-lock"></i>
+            </span>
+          </div>
+          <div class="container-login100-form-btn p-t-10">
+            <button class="login100-form-btn login-btn">Login</button>
+          </div>
+          <div class="container-login100-form-btn p-t-10" style="display: none;margin-top: 50px;" id="updateLicense">
+            <form enctype="multipart/form-data" style="display: none;">
+              <input id="license" type="file" name="file" >
+            </form>
+            <button class="login100-form-btn" id="submitLicense">鏇存柊璁稿彲璇�</button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <script type="text/javascript" src="../../static/js/tools/main.min.js"></script>
+    <script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
+    <script type="text/javascript" src="../../static/js/tools/md5.js"></script>
+    <script type="text/javascript" src="../../static/layer/layer.js"></script>
+    <script type="text/javascript" src="../../static/js/common.js"></script>
+    <script>
+      // remember pwd
+      $(function () {
+        var oldUserName = localStorage.getItem('oldUserName');
+        var oldPass = localStorage.getItem('oldPass');
+        if(oldUserName){
+          $('#username').val(oldUserName);
+        }
+        if(oldPass){
+          $('#password').val(oldPass);
+        }
+      })
+
+      window.onload = function(){document.getElementById("username").focus();}
+
+      $(document).on('click','.login-btn', function () {
+        let username = $("#username").val();
+        if (username === "") {
+          layer.tips('璇疯緭鍏ョ櫥褰曡处鍙�', '#username', {tips: [4, '#ff0000']});
+          return;
+        }
+        let password = $("#password").val();
+        if (password === "") {
+          layer.tips('璇疯緭鍏ュ瘑鐮�', '#password', {tips: [4, '#ff0000']});
+          return;
+        }
+        $.ajax({
+          url: baseUrl+"/login.action",
+          data: {
+            username: username,
+            password: hex_md5(password)
+          },
+          method: 'POST',
+          success: function (res) {
+            if (res.code === 200){
+              localStorage.setItem("token", res.data.token);
+              localStorage.setItem("username", res.data.username);
+              window.location.href = "../index.html";
+            } else if (res.code === 10001) {
+              layer.tips(res.msg, '#username', {tips: [4, '#ff0000']});
+            } else if (res.code === 10002) {
+              layer.tips(res.msg, '#username', {tips: [4, '#ff0000']});
+            } else if (res.code === 10003) {
+              layer.tips(res.msg, '#password', {tips: [4, '#ff0000']});
+            } else if (res.code == 20001) {
+              layer.tips(res.msg, '.login-btn', {tips: [3, '#ff0000']});
+              $("#updateLicense").show()
+            } else {
+              layer.tips(res.msg, '.login-btn', {tips: [3, '#ff0000']});
+            }
+          }
+        });
+      });
+
+      $('body').keydown(function () {
+        if (event.keyCode === 13) {
+          $(".login-btn").click();
+        }
+      });
+
+      //鏇存柊璁稿彲璇�
+      $("#submitLicense").on("click",() => {
+        $("#license").click()
+      })
+
+      //涓婁紶骞舵洿鏂拌鍙瘉
+      $("#license").on("change",(evt) => {
+        var files = evt.target.files;
+        let formData = new FormData();
+        formData.append("file", files[0])
+        $.ajax({
+          url: baseUrl+"/license/updateLicense",
+          headers: {'token': localStorage.getItem('token')},
+          data: formData,
+          method: 'POST',
+          cache: false,
+          processData: false,
+          contentType: false,
+          success: function (res) {
+            if (res.code == 200) {
+              layer.msg('鏇存柊鎴愬姛', {time: 1000}, () => {
+                parent.location.reload()
+              });
+            }else{
+              layer.msg(res.msg,{time:2000},() => {
+                parent.location.reload()
+              })
+            }
+          }
+        })
+      })
+    </script>
+  </body>
+</html>
diff --git a/src/main/webapp/views/index.html b/src/main/webapp/views/index.html
index 60a5625..e3ce393 100644
--- a/src/main/webapp/views/index.html
+++ b/src/main/webapp/views/index.html
@@ -41,6 +41,9 @@
       </li>
     </ul>
     <ul class="layui-nav layui-layout-right">
+      <li class="layui-nav-item" lay-unselect id="licenseShow" style="display: none;user-select: none;">
+        <div style="color: red;">璁稿彲璇佹湁鏁堟湡锛�<span id="licenseDays">29</span>澶�</div>
+      </li>
       <li class="layui-nav-item" lay-unselect>
         <a ew-event="note" title="渚跨"><i class="layui-icon layui-icon-note"></i></a>
       </li>
@@ -140,6 +143,23 @@
       }
     });
 
+    $.ajax({
+      url: baseUrl + "/license/getLicenseDays",
+      headers: {'token': localStorage.getItem('token')},
+      method: 'POST',
+      success: function (res) {
+        if (res.code == 200) {
+          let days = res.data
+          if (days <= 30) {
+            $("#licenseShow").show()
+            $("#licenseDays").html(days)
+          }
+        }else {
+          top.location.href = baseUrl + "/login";
+        }
+      }
+    });
+
     // 榛樿鍔犺浇涓婚〉
     index.loadHome({
       menuPath: baseUrl+'/views/home/navigation.html',
diff --git a/src/main/webapp/views/login.html b/src/main/webapp/views/login.html
index dba7bf1..b4c209b 100644
--- a/src/main/webapp/views/login.html
+++ b/src/main/webapp/views/login.html
@@ -87,6 +87,12 @@
           <div class="container-login100-form-btn p-t-10">
             <button class="login100-form-btn login-btn">Login</button>
           </div>
+          <div class="container-login100-form-btn p-t-10" style="display: none;margin-top: 50px;" id="updateLicense">
+            <form enctype="multipart/form-data" style="display: none;">
+              <input id="license" type="file" name="file" >
+            </form>
+            <button class="login100-form-btn" id="submitLicense">鏇存柊璁稿彲璇�</button>
+          </div>
         </div>
       </div>
     </div>
@@ -140,6 +146,9 @@
               layer.tips(res.msg, '#username', {tips: [4, '#ff0000']});
             } else if (res.code === 10003) {
               layer.tips(res.msg, '#password', {tips: [4, '#ff0000']});
+            } else if (res.code == 20001) {
+              layer.tips(res.msg, '.login-btn', {tips: [3, '#ff0000']});
+              $("#updateLicense").show()
             } else {
               layer.tips(res.msg, '.login-btn', {tips: [3, '#ff0000']});
             }
@@ -152,6 +161,38 @@
           $(".login-btn").click();
         }
       });
+
+      //鏇存柊璁稿彲璇�
+      $("#submitLicense").on("click",() => {
+        $("#license").click()
+      })
+
+      //涓婁紶骞舵洿鏂拌鍙瘉
+      $("#license").on("change",(evt) => {
+        var files = evt.target.files;
+        let formData = new FormData();
+        formData.append("file", files[0])
+        $.ajax({
+          url: baseUrl+"/license/updateLicense",
+          headers: {'token': localStorage.getItem('token')},
+          data: formData,
+          method: 'POST',
+          cache: false,
+          processData: false,
+          contentType: false,
+          success: function (res) {
+            if (res.code == 200) {
+              layer.msg('鏇存柊鎴愬姛', {time: 1000}, () => {
+                parent.location.reload()
+              });
+            }else{
+              layer.msg(res.msg,{time:2000},() => {
+                parent.location.reload()
+              })
+            }
+          }
+        })
+      })
     </script>
   </body>
 </html>

--
Gitblit v1.9.1