自动化立体仓库 - WMS系统
whycq
2023-10-18 ff61738813a553bfbf8f4f1fec6e001e3c8e4415
# 移植台州三凯许可证
6个文件已修改
5个文件已添加
474 ■■■■■ 已修改文件
pom.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/CodeRes.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/web/AuthController.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/system/controller/LicenseCreatorController.java 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/system/entity/license/LicenseCheckListener.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application.yml 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/license.lic 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/publicCerts.keystore 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/home/easy_login.html 182 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/index.html 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/login.html 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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>
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-拣料任务";
    String NO_COMB_700 = "700-请先组托";
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);
src/main/java/com/zy/system/controller/LicenseCreatorController.java
New file
@@ -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("许可证更新失败");
    }
}
src/main/java/com/zy/system/entity/license/LicenseCheckListener.java
New file
@@ -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;
    }
}
src/main/resources/application.yml
@@ -53,4 +53,13 @@
#erp
erp:
  enable: false
  enable: false
#License相关配置
license:
  subject: pswms
  publicAlias: publicCert
  storePass: public_zhongyang_123456789
  licensePath: license.lic
  publicKeysStorePath: publicCerts.keystore
src/main/resources/license.lic
Binary files differ
src/main/resources/publicCerts.keystore
Binary files differ
src/main/webapp/views/home/easy_login.html
New file
@@ -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>
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',
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>