| | |
| | | !.mvn/wrapper/maven-wrapper.jar |
| | | !**/src/main/** |
| | | !**/src/test/** |
| | | /src/main/resources/license.lic |
| | | |
| | | ### STS ### |
| | | .apt_generated |
| | |
| | | <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> |
| | |
| | | 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-请先组托"; |
| | |
| | | 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; |
| | |
| | | @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); |
New file |
| | |
| | | package com.zy.system.controller; |
| | | |
| | | import com.core.annotations.ManagerAuth; |
| | | 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.util.ClassUtils; |
| | | import org.springframework.web.bind.annotation.RequestBody; |
| | | 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.text.SimpleDateFormat; |
| | | import java.time.temporal.ChronoUnit; |
| | | import java.util.Date; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | import java.util.prefs.Preferences; |
| | | |
| | | /** |
| | | * |
| | | * 用于生成证书文件,不能放在给客户部署的代码里 |
| | | */ |
| | | @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("许可证更新失败"); |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.zy.system.entity.license; |
| | | |
| | | import org.apache.logging.log4j.LogManager; |
| | | import org.apache.logging.log4j.Logger; |
| | | |
| | | import java.net.InetAddress; |
| | | import java.net.NetworkInterface; |
| | | import java.net.SocketException; |
| | | import java.util.ArrayList; |
| | | import java.util.Enumeration; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 用于获取客户服务器的基本信息,如:IP、Mac地址、CPU序列号、主板序列号等 |
| | | */ |
| | | public abstract class AbstractServerInfos { |
| | | private static Logger logger = LogManager.getLogger(AbstractServerInfos.class); |
| | | |
| | | /** |
| | | * 组装需要额外校验的License参数 |
| | | */ |
| | | public LicenseCheck getServerInfos(){ |
| | | LicenseCheck result = new LicenseCheck(); |
| | | |
| | | try { |
| | | result.setIpAddress(this.getIpAddress()); |
| | | result.setMacAddress(this.getMacAddress()); |
| | | result.setCpuSerial(this.getCPUSerial()); |
| | | result.setMainBoardSerial(this.getMainBoardSerial()); |
| | | }catch (Exception e){ |
| | | logger.error("获取服务器硬件信息失败",e); |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * 获取IP地址 |
| | | */ |
| | | protected abstract List<String> getIpAddress() throws Exception; |
| | | |
| | | /** |
| | | * 获取Mac地址 |
| | | */ |
| | | protected abstract List<String> getMacAddress() throws Exception; |
| | | |
| | | /** |
| | | * 获取CPU序列号 |
| | | */ |
| | | protected abstract String getCPUSerial() throws Exception; |
| | | |
| | | /** |
| | | * 获取主板序列号 |
| | | */ |
| | | protected abstract String getMainBoardSerial() throws Exception; |
| | | |
| | | /** |
| | | * 获取当前服务器所有符合条件的InetAddress |
| | | */ |
| | | protected List<InetAddress> getLocalAllInetAddress() throws Exception { |
| | | List<InetAddress> result = new ArrayList<>(4); |
| | | |
| | | // 遍历所有的网络接口 |
| | | for (Enumeration networkInterfaces = NetworkInterface.getNetworkInterfaces(); networkInterfaces.hasMoreElements(); ) { |
| | | NetworkInterface iface = (NetworkInterface) networkInterfaces.nextElement(); |
| | | // 在所有的接口下再遍历IP |
| | | for (Enumeration inetAddresses = iface.getInetAddresses(); inetAddresses.hasMoreElements(); ) { |
| | | InetAddress inetAddr = (InetAddress) inetAddresses.nextElement(); |
| | | |
| | | //排除LoopbackAddress、SiteLocalAddress、LinkLocalAddress、MulticastAddress类型的IP地址 |
| | | if(!inetAddr.isLoopbackAddress() /*&& !inetAddr.isSiteLocalAddress()*/ |
| | | && !inetAddr.isLinkLocalAddress() && !inetAddr.isMulticastAddress()){ |
| | | result.add(inetAddr); |
| | | } |
| | | } |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * 获取某个网络接口的Mac地址 |
| | | */ |
| | | protected String getMacByInetAddress(InetAddress inetAddr){ |
| | | try { |
| | | byte[] mac = NetworkInterface.getByInetAddress(inetAddr).getHardwareAddress(); |
| | | StringBuffer stringBuffer = new StringBuffer(); |
| | | |
| | | for(int i=0;i<mac.length;i++){ |
| | | if(i != 0) { |
| | | stringBuffer.append("-"); |
| | | } |
| | | |
| | | //将十六进制byte转化为字符串 |
| | | String temp = Integer.toHexString(mac[i] & 0xff); |
| | | if(temp.length() == 1){ |
| | | stringBuffer.append("0" + temp); |
| | | }else{ |
| | | stringBuffer.append(temp); |
| | | } |
| | | } |
| | | |
| | | return stringBuffer.toString().toUpperCase(); |
| | | } catch (SocketException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | |
| | | return null; |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.zy.system.entity.license; |
| | | |
| | | import de.schlichtherle.license.AbstractKeyStoreParam; |
| | | |
| | | import java.io.*; |
| | | |
| | | /** |
| | | * 自定义KeyStoreParam,用于将公私钥存储文件存放到其他磁盘位置而不是项目中 |
| | | */ |
| | | public class CustomKeyStoreParam extends AbstractKeyStoreParam { |
| | | |
| | | /** |
| | | * 公钥/私钥在磁盘上的存储路径 |
| | | */ |
| | | private String storePath; |
| | | private String alias; |
| | | private String storePwd; |
| | | private String keyPwd; |
| | | |
| | | public CustomKeyStoreParam(Class clazz, String resource, String alias, String storePwd, String keyPwd) { |
| | | super(clazz, resource); |
| | | this.storePath = resource; |
| | | this.alias = alias; |
| | | this.storePwd = storePwd; |
| | | this.keyPwd = keyPwd; |
| | | } |
| | | |
| | | |
| | | @Override |
| | | public String getAlias() { |
| | | return alias; |
| | | } |
| | | |
| | | @Override |
| | | public String getStorePwd() { |
| | | return storePwd; |
| | | } |
| | | |
| | | @Override |
| | | public String getKeyPwd() { |
| | | return keyPwd; |
| | | } |
| | | |
| | | /** |
| | | * 复写de.schlichtherle.license.AbstractKeyStoreParam的getStream()方法<br/> |
| | | * 用于将公私钥存储文件存放到其他磁盘位置而不是项目中 |
| | | */ |
| | | @Override |
| | | public InputStream getStream() throws IOException { |
| | | final InputStream in = new FileInputStream(new File(storePath)); |
| | | if (null == in) { |
| | | throw new FileNotFoundException(storePath); |
| | | } |
| | | |
| | | return in; |
| | | } |
| | | } |
New file |
| | |
| | | package com.zy.system.entity.license; |
| | | |
| | | import com.core.common.Cools; |
| | | import de.schlichtherle.license.LicenseContent; |
| | | import de.schlichtherle.license.LicenseContentException; |
| | | import de.schlichtherle.license.LicenseManager; |
| | | import de.schlichtherle.license.LicenseNotary; |
| | | import de.schlichtherle.license.LicenseParam; |
| | | import de.schlichtherle.license.NoLicenseInstalledException; |
| | | import de.schlichtherle.xml.GenericCertificate; |
| | | import org.apache.logging.log4j.LogManager; |
| | | import org.apache.logging.log4j.Logger; |
| | | |
| | | import java.beans.XMLDecoder; |
| | | import java.io.BufferedInputStream; |
| | | import java.io.ByteArrayInputStream; |
| | | import java.io.UnsupportedEncodingException; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 自定义LicenseManager,用于增加额外的服务器硬件信息校验 |
| | | */ |
| | | public class CustomLicenseManager extends LicenseManager{ |
| | | private static Logger logger = LogManager.getLogger(CustomLicenseManager.class); |
| | | |
| | | //XML编码 |
| | | private static final String XML_CHARSET = "UTF-8"; |
| | | //默认BUFSIZE |
| | | private static final int DEFAULT_BUFSIZE = 8 * 1024; |
| | | |
| | | public CustomLicenseManager() { |
| | | |
| | | } |
| | | |
| | | public CustomLicenseManager(LicenseParam param) { |
| | | super(param); |
| | | } |
| | | |
| | | /** |
| | | * 复写create方法 |
| | | */ |
| | | @Override |
| | | protected synchronized byte[] create( |
| | | LicenseContent content, |
| | | LicenseNotary notary) |
| | | throws Exception { |
| | | initialize(content); |
| | | this.validateCreate(content); |
| | | final GenericCertificate certificate = notary.sign(content); |
| | | return getPrivacyGuard().cert2key(certificate); |
| | | } |
| | | |
| | | /** |
| | | * 复写install方法,其中validate方法调用本类中的validate方法,校验IP地址、Mac地址等其他信息 |
| | | */ |
| | | @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地址等其他信息 |
| | | */ |
| | | @Override |
| | | protected synchronized LicenseContent verify(final LicenseNotary notary) |
| | | throws Exception { |
| | | GenericCertificate certificate = getCertificate(); |
| | | |
| | | // Load license key from preferences, |
| | | final byte[] key = getLicenseKey(); |
| | | if (null == key){ |
| | | throw new NoLicenseInstalledException(getLicenseParam().getSubject()); |
| | | } |
| | | |
| | | certificate = getPrivacyGuard().key2cert(key); |
| | | notary.verify(certificate); |
| | | final LicenseContent content = (LicenseContent)this.load(certificate.getEncoded()); |
| | | this.validate(content); |
| | | setCertificate(certificate); |
| | | |
| | | return content; |
| | | } |
| | | |
| | | /** |
| | | * 校验生成证书的参数信息 |
| | | */ |
| | | protected synchronized void validateCreate(final LicenseContent content) |
| | | throws LicenseContentException { |
| | | final LicenseParam param = getLicenseParam(); |
| | | |
| | | final Date now = new Date(); |
| | | final Date notBefore = content.getNotBefore(); |
| | | final Date notAfter = content.getNotAfter(); |
| | | if (null != notAfter && now.after(notAfter)){ |
| | | throw new LicenseContentException("证书失效时间不能早于当前时间"); |
| | | } |
| | | if (null != notBefore && null != notAfter && notAfter.before(notBefore)){ |
| | | throw new LicenseContentException("证书生效时间不能晚于证书失效时间"); |
| | | } |
| | | final String consumerType = content.getConsumerType(); |
| | | if (null == consumerType){ |
| | | throw new LicenseContentException("用户类型不能为空"); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 复写validate方法,增加IP地址、Mac地址等其他信息校验 |
| | | */ |
| | | @Override |
| | | protected synchronized void validate(final LicenseContent content) |
| | | throws LicenseContentException { |
| | | //1. 首先调用父类的validate方法 |
| | | super.validate(content); |
| | | |
| | | //2. 然后校验自定义的License参数 |
| | | //License中可被允许的参数信息 |
| | | LicenseCheck expectedCheckModel = (LicenseCheck) content.getExtra(); |
| | | //当前服务器真实的参数信息 |
| | | LicenseCheck serverCheckModel = getServerInfos(); |
| | | |
| | | if(expectedCheckModel != null && serverCheckModel != null){ |
| | | //校验IP地址 |
| | | if(!checkIpAddress(expectedCheckModel.getIpAddress(),serverCheckModel.getIpAddress())){ |
| | | throw new LicenseContentException("当前服务器的IP没在授权范围内"); |
| | | } |
| | | |
| | | //校验Mac地址 |
| | | if(!checkIpAddress(expectedCheckModel.getMacAddress(),serverCheckModel.getMacAddress())){ |
| | | throw new LicenseContentException("当前服务器的Mac地址没在授权范围内"); |
| | | } |
| | | |
| | | //校验主板序列号 |
| | | if(!checkSerial(expectedCheckModel.getMainBoardSerial(),serverCheckModel.getMainBoardSerial())){ |
| | | throw new LicenseContentException("当前服务器的主板序列号没在授权范围内"); |
| | | } |
| | | |
| | | //校验CPU序列号 |
| | | if(!checkSerial(expectedCheckModel.getCpuSerial(),serverCheckModel.getCpuSerial())){ |
| | | throw new LicenseContentException("当前服务器的CPU序列号没在授权范围内"); |
| | | } |
| | | }else{ |
| | | throw new LicenseContentException("不能获取服务器硬件信息"); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 重写XMLDecoder解析XML |
| | | */ |
| | | private Object load(String encoded){ |
| | | BufferedInputStream inputStream = null; |
| | | XMLDecoder decoder = null; |
| | | try { |
| | | inputStream = new BufferedInputStream(new ByteArrayInputStream(encoded.getBytes(XML_CHARSET))); |
| | | |
| | | decoder = new XMLDecoder(new BufferedInputStream(inputStream, DEFAULT_BUFSIZE),null,null); |
| | | |
| | | return decoder.readObject(); |
| | | } catch (UnsupportedEncodingException e) { |
| | | e.printStackTrace(); |
| | | } finally { |
| | | try { |
| | | if(decoder != null){ |
| | | decoder.close(); |
| | | } |
| | | if(inputStream != null){ |
| | | inputStream.close(); |
| | | } |
| | | } catch (Exception e) { |
| | | logger.error("XMLDecoder解析XML失败",e); |
| | | } |
| | | } |
| | | |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * 获取当前服务器需要额外校验的License参数 |
| | | */ |
| | | private LicenseCheck getServerInfos(){ |
| | | //操作系统类型 |
| | | String osName = System.getProperty("os.name").toLowerCase(); |
| | | AbstractServerInfos abstractServerInfos = null; |
| | | |
| | | //根据不同操作系统类型选择不同的数据获取方法 |
| | | if (osName.startsWith("windows")) { |
| | | abstractServerInfos = new WindowsServerInfos(); |
| | | } else if (osName.startsWith("linux")) { |
| | | // abstractServerInfos = new LinuxServerInfos(); |
| | | }else{//其他服务器类型 |
| | | abstractServerInfos = new WindowsServerInfos(); |
| | | } |
| | | |
| | | return abstractServerInfos.getServerInfos(); |
| | | } |
| | | |
| | | /** |
| | | * 校验当前服务器的IP/Mac地址是否在可被允许的IP范围内<br/> |
| | | * 如果存在IP在可被允许的IP/Mac地址范围内,则返回true |
| | | */ |
| | | 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等)序列号是否在可允许范围内 |
| | | */ |
| | | private boolean checkSerial(String expectedSerial,String serverSerial){ |
| | | if(!Cools.isEmpty(expectedSerial)){ |
| | | if(!Cools.isEmpty(serverSerial)){ |
| | | if(expectedSerial.equals(serverSerial)){ |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | }else{ |
| | | return true; |
| | | } |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.zy.system.entity.license; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serializable; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 自定义需要校验的License参数 |
| | | */ |
| | | @Data |
| | | public class LicenseCheck implements Serializable { |
| | | |
| | | private static final long serialVersionUID = 8600137500316662317L; |
| | | /** |
| | | * 可被允许的IP地址 |
| | | */ |
| | | private List<String> ipAddress; |
| | | |
| | | /** |
| | | * 可被允许的MAC地址 |
| | | */ |
| | | private List<String> macAddress; |
| | | |
| | | /** |
| | | * 可被允许的CPU序列号 |
| | | */ |
| | | private String cpuSerial; |
| | | |
| | | /** |
| | | * 可被允许的主板序列号 |
| | | */ |
| | | private String mainBoardSerial; |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return "LicenseCheckModel{" + |
| | | "ipAddress=" + ipAddress + |
| | | ", macAddress=" + macAddress + |
| | | ", cpuSerial='" + cpuSerial + '\'' + |
| | | ", mainBoardSerial='" + mainBoardSerial + '\'' + |
| | | '}'; |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | 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; |
| | | } |
| | | } |
New file |
| | |
| | | package com.zy.system.entity.license; |
| | | |
| | | import de.schlichtherle.license.*; |
| | | import org.apache.logging.log4j.LogManager; |
| | | import org.apache.logging.log4j.Logger; |
| | | |
| | | import javax.security.auth.x500.X500Principal; |
| | | import java.io.File; |
| | | import java.text.MessageFormat; |
| | | import java.util.prefs.Preferences; |
| | | |
| | | /** |
| | | * License生成类 |
| | | */ |
| | | public class LicenseCreator { |
| | | private static Logger logger = LogManager.getLogger(LicenseCreator.class); |
| | | private final static X500Principal DEFAULT_HOLDER_AND_ISSUER = new X500Principal("CN=localhost, OU=localhost, O=localhost, L=SH, ST=SH, C=CN"); |
| | | private LicenseCreatorParam param; |
| | | |
| | | public LicenseCreator(LicenseCreatorParam param) { |
| | | this.param = param; |
| | | } |
| | | |
| | | /** |
| | | * 生成License证书 |
| | | */ |
| | | public boolean generateLicense(){ |
| | | try { |
| | | LicenseManager licenseManager = new CustomLicenseManager(initLicenseParam()); |
| | | LicenseContent licenseContent = initLicenseContent(); |
| | | |
| | | licenseManager.store(licenseContent,new File(param.getLicensePath())); |
| | | |
| | | return true; |
| | | }catch (Exception e){ |
| | | logger.error(MessageFormat.format("证书生成失败:{0}",param),e); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 初始化证书生成参数 |
| | | */ |
| | | private LicenseParam initLicenseParam(){ |
| | | Preferences preferences = Preferences.userNodeForPackage(LicenseCreator.class); |
| | | |
| | | //设置对证书内容加密的秘钥 |
| | | CipherParam cipherParam = new DefaultCipherParam(param.getStorePass()); |
| | | |
| | | KeyStoreParam privateStoreParam = new CustomKeyStoreParam(LicenseCreator.class |
| | | ,param.getPrivateKeysStorePath() |
| | | ,param.getPrivateAlias() |
| | | ,param.getStorePass() |
| | | ,param.getKeyPass()); |
| | | |
| | | LicenseParam licenseParam = new DefaultLicenseParam(param.getSubject() |
| | | ,preferences |
| | | ,privateStoreParam |
| | | ,cipherParam); |
| | | |
| | | return licenseParam; |
| | | } |
| | | |
| | | /** |
| | | * 设置证书生成正文信息 |
| | | */ |
| | | private LicenseContent initLicenseContent(){ |
| | | LicenseContent licenseContent = new LicenseContent(); |
| | | licenseContent.setHolder(DEFAULT_HOLDER_AND_ISSUER); |
| | | licenseContent.setIssuer(DEFAULT_HOLDER_AND_ISSUER); |
| | | |
| | | licenseContent.setSubject(param.getSubject()); |
| | | licenseContent.setIssued(param.getIssuedTime()); |
| | | licenseContent.setNotBefore(param.getIssuedTime()); |
| | | licenseContent.setNotAfter(param.getExpiryTime()); |
| | | licenseContent.setConsumerType(param.getConsumerType()); |
| | | licenseContent.setConsumerAmount(param.getConsumerAmount()); |
| | | licenseContent.setInfo(param.getDescription()); |
| | | |
| | | //扩展校验服务器硬件信息 |
| | | licenseContent.setExtra(param.getLicenseCheck()); |
| | | |
| | | return licenseContent; |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.zy.system.entity.license; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serializable; |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * License生成类需要的参数 |
| | | */ |
| | | @Data |
| | | public class LicenseCreatorParam implements Serializable { |
| | | |
| | | private static final long serialVersionUID = -7793154252684580872L; |
| | | /** |
| | | * 证书subject |
| | | */ |
| | | private String subject; |
| | | |
| | | /** |
| | | * 密钥别称 |
| | | */ |
| | | private String privateAlias; |
| | | |
| | | /** |
| | | * 密钥密码(需要妥善保管,不能让使用者知道) |
| | | */ |
| | | private String keyPass; |
| | | |
| | | /** |
| | | * 访问秘钥库的密码 |
| | | */ |
| | | private String storePass; |
| | | |
| | | /** |
| | | * 证书生成路径 |
| | | */ |
| | | private String licensePath; |
| | | |
| | | /** |
| | | * 密钥库存储路径 |
| | | */ |
| | | private String privateKeysStorePath; |
| | | |
| | | /** |
| | | * 证书生效时间 |
| | | */ |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
| | | private Date issuedTime = new Date(); |
| | | |
| | | /** |
| | | * 证书失效时间 |
| | | */ |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
| | | private Date expiryTime; |
| | | |
| | | /** |
| | | * 用户类型 |
| | | */ |
| | | private String consumerType = "user"; |
| | | |
| | | /** |
| | | * 用户数量 |
| | | */ |
| | | private Integer consumerAmount = 1; |
| | | |
| | | /** |
| | | * 描述信息 |
| | | */ |
| | | private String description = ""; |
| | | |
| | | /** |
| | | * 额外的服务器硬件校验信息 |
| | | */ |
| | | private LicenseCheck licenseCheck; |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return "LicenseCreatorParam{" + |
| | | "subject='" + subject + '\'' + |
| | | ", privateAlias='" + privateAlias + '\'' + |
| | | ", keyPass='" + keyPass + '\'' + |
| | | ", storePass='" + storePass + '\'' + |
| | | ", licensePath='" + licensePath + '\'' + |
| | | ", privateKeysStorePath='" + privateKeysStorePath + '\'' + |
| | | ", issuedTime=" + issuedTime + |
| | | ", expiryTime=" + expiryTime + |
| | | ", consumerType='" + consumerType + '\'' + |
| | | ", consumerAmount=" + consumerAmount + |
| | | ", description='" + description + '\'' + |
| | | ", licenseCheck=" + licenseCheck + |
| | | '}'; |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.zy.system.entity.license; |
| | | |
| | | import de.schlichtherle.license.LicenseManager; |
| | | import de.schlichtherle.license.LicenseParam; |
| | | |
| | | public class LicenseManagerHolder { |
| | | |
| | | private static volatile LicenseManager LICENSE_MANAGER; |
| | | |
| | | public static LicenseManager getInstance(LicenseParam param) { |
| | | if (LICENSE_MANAGER == null) { |
| | | synchronized (LicenseManagerHolder.class) { |
| | | if (LICENSE_MANAGER == null) { |
| | | LICENSE_MANAGER = new CustomLicenseManager(param); |
| | | } |
| | | } |
| | | } |
| | | |
| | | return LICENSE_MANAGER; |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.zy.system.entity.license; |
| | | |
| | | import de.schlichtherle.license.*; |
| | | import org.apache.logging.log4j.LogManager; |
| | | import org.apache.logging.log4j.Logger; |
| | | |
| | | import java.io.File; |
| | | import java.text.DateFormat; |
| | | import java.text.MessageFormat; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.prefs.Preferences; |
| | | |
| | | /** |
| | | * License校验类 |
| | | */ |
| | | public class LicenseVerify { |
| | | private static Logger logger = LogManager.getLogger(LicenseVerify.class); |
| | | |
| | | /** |
| | | * 安装License证书 |
| | | */ |
| | | public synchronized LicenseContent install(LicenseVerifyParam param){ |
| | | LicenseContent result = null; |
| | | 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); |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * 校验License证书 |
| | | */ |
| | | public boolean verify(){ |
| | | try { |
| | | LicenseManager licenseManager = LicenseManagerHolder.getInstance(null); |
| | | DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
| | | |
| | | if (!updateSystemTime()) { |
| | | //时间更新失败,系统时间被更改 |
| | | return false; |
| | | } |
| | | |
| | | LicenseContent licenseContent = licenseManager.verify(); |
| | | logger.info(MessageFormat.format("许可证校验通过,许可证有效期:{0} - {1}",format.format(licenseContent.getNotBefore()),format.format(licenseContent.getNotAfter()))); |
| | | return true; |
| | | }catch (Exception e){ |
| | | logger.error("许可证校验失败!",e); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 校验License证书并获取证书信息 |
| | | */ |
| | | public LicenseContent getVerifyInfo(){ |
| | | LicenseManager licenseManager = LicenseManagerHolder.getInstance(null); |
| | | |
| | | if (!updateSystemTime()) { |
| | | //时间更新失败,系统时间被更改 |
| | | return null; |
| | | } |
| | | |
| | | //校验证书 |
| | | try { |
| | | LicenseContent licenseContent = licenseManager.verify(); |
| | | return licenseContent; |
| | | }catch (Exception e){ |
| | | logger.error("许可证校验失败!",e); |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 初始化证书生成参数 |
| | | * @param param License校验类需要的参数 |
| | | * @return de.schlichtherle.license.LicenseParam |
| | | */ |
| | | private LicenseParam initLicenseParam(LicenseVerifyParam param){ |
| | | Preferences preferences = Preferences.userNodeForPackage(LicenseVerify.class); |
| | | |
| | | CipherParam cipherParam = new DefaultCipherParam(param.getStorePass()); |
| | | |
| | | KeyStoreParam publicStoreParam = new CustomKeyStoreParam(LicenseVerify.class |
| | | ,param.getPublicKeysStorePath() |
| | | ,param.getPublicAlias() |
| | | ,param.getStorePass() |
| | | ,null); |
| | | |
| | | return new DefaultLicenseParam(param.getSubject() |
| | | ,preferences |
| | | ,publicStoreParam |
| | | ,cipherParam); |
| | | } |
| | | |
| | | /** |
| | | * 更新时间到注册表中 |
| | | */ |
| | | private boolean updateSystemTime() { |
| | | // 获取用户根节点 |
| | | Preferences userRoot = Preferences.userRoot(); |
| | | // 获取指定路径下的节点 |
| | | Preferences node = userRoot.node("/zhongyang"); |
| | | String key = "time"; |
| | | // 读取注册表 |
| | | String value = node.get(key, null); |
| | | if (value != null) { |
| | | long originTime = Long.parseLong(value); |
| | | long now = System.currentTimeMillis(); |
| | | long diff = now - originTime;//现在时间 - 源时间 = 时间差 |
| | | if (diff > 0) { |
| | | //时间差大于0才允许更新注册表时间 |
| | | node.put(key, String.valueOf(System.currentTimeMillis())); |
| | | return true; |
| | | } |
| | | }else { |
| | | // 写入注册表 |
| | | node.put(key, String.valueOf(System.currentTimeMillis())); |
| | | return true; |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.zy.system.entity.license; |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * 校验签名文件 |
| | | */ |
| | | @Data |
| | | public class LicenseVerifyParam { |
| | | |
| | | /** |
| | | * 证书subject |
| | | */ |
| | | private String subject; |
| | | |
| | | /** |
| | | * 公钥别称 |
| | | */ |
| | | private String publicAlias; |
| | | |
| | | /** |
| | | * 访问公钥库的密码 |
| | | */ |
| | | private String storePass; |
| | | |
| | | /** |
| | | * 证书生成路径 |
| | | */ |
| | | private String licensePath; |
| | | |
| | | /** |
| | | * 密钥库存储路径 |
| | | */ |
| | | private String publicKeysStorePath; |
| | | |
| | | public LicenseVerifyParam() { |
| | | |
| | | } |
| | | |
| | | public LicenseVerifyParam(String subject, String publicAlias, String storePass, String licensePath, String publicKeysStorePath) { |
| | | this.subject = subject; |
| | | this.publicAlias = publicAlias; |
| | | this.storePass = storePass; |
| | | this.licensePath = licensePath; |
| | | this.publicKeysStorePath = publicKeysStorePath; |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.zy.system.entity.license; |
| | | |
| | | import java.net.InetAddress; |
| | | import java.util.List; |
| | | import java.util.Scanner; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * 用于获取客户Windows服务器的基本信息 |
| | | */ |
| | | public class WindowsServerInfos extends AbstractServerInfos { |
| | | |
| | | @Override |
| | | protected List<String> getIpAddress() throws Exception { |
| | | List<String> result = null; |
| | | |
| | | //获取所有网络接口 |
| | | List<InetAddress> inetAddresses = getLocalAllInetAddress(); |
| | | |
| | | if(inetAddresses != null && inetAddresses.size() > 0){ |
| | | result = inetAddresses.stream().map(InetAddress::getHostAddress).distinct().map(String::toLowerCase).collect(Collectors.toList()); |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | @Override |
| | | protected List<String> getMacAddress() throws Exception { |
| | | List<String> result = null; |
| | | |
| | | //1. 获取所有网络接口 |
| | | List<InetAddress> inetAddresses = getLocalAllInetAddress(); |
| | | |
| | | if(inetAddresses != null && inetAddresses.size() > 0){ |
| | | //2. 获取所有网络接口的Mac地址 |
| | | result = inetAddresses.stream().map(this::getMacByInetAddress).distinct().collect(Collectors.toList()); |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | @Override |
| | | protected String getCPUSerial() throws Exception { |
| | | //序列号 |
| | | String serialNumber = ""; |
| | | |
| | | //使用WMIC获取CPU序列号 |
| | | Process process = Runtime.getRuntime().exec("wmic cpu get processorid"); |
| | | process.getOutputStream().close(); |
| | | Scanner scanner = new Scanner(process.getInputStream()); |
| | | |
| | | if(scanner.hasNext()){ |
| | | scanner.next(); |
| | | } |
| | | |
| | | if(scanner.hasNext()){ |
| | | serialNumber = scanner.next().trim(); |
| | | } |
| | | |
| | | scanner.close(); |
| | | return serialNumber; |
| | | } |
| | | |
| | | @Override |
| | | protected String getMainBoardSerial() throws Exception { |
| | | //序列号 |
| | | String serialNumber = ""; |
| | | |
| | | //使用WMIC获取主板序列号 |
| | | Process process = Runtime.getRuntime().exec("wmic baseboard get serialnumber"); |
| | | process.getOutputStream().close(); |
| | | Scanner scanner = new Scanner(process.getInputStream()); |
| | | |
| | | if(scanner.hasNext()){ |
| | | scanner.next(); |
| | | } |
| | | |
| | | if(scanner.hasNext()){ |
| | | serialNumber = scanner.next().trim(); |
| | | } |
| | | |
| | | scanner.close(); |
| | | return serialNumber; |
| | | } |
| | | } |
| | |
| | | swagger: |
| | | enable: false |
| | | |
| | | #License相关配置 |
| | | license: |
| | | subject: zjfnasrs |
| | | publicAlias: publicCert |
| | | storePass: public_zhongyang_123456789 |
| | | licensePath: license.lic |
| | | publicKeysStorePath: publicCerts.keystore |
| | | |
| | | # 下位机配置 |
| | | wcs-slave: |
| | | # 双深 |
New file |
| | |
| | | <!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> |
| | |
| | | </li> |
| | | </ul> |
| | | <ul class="layui-nav layui-layout-right"> |
| | | <li class="layui-nav-item" lay-unselect> |
| | | <a ew-event="note" title="便签"><i class="layui-icon layui-icon-note"></i></a> |
| | | <!-- <li class="layui-nav-item" lay-unselect>--> |
| | | <!-- <a ew-event="note" title="便签"><i class="layui-icon layui-icon-note"></i></a>--> |
| | | <!-- </li>--> |
| | | <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 layui-hide-xs" lay-unselect> |
| | | <a ew-event="fullScreen" title="全屏"><i class="layui-icon layui-icon-screen-full"></i></a> |
| | |
| | | } |
| | | }); |
| | | |
| | | $.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', |
| | |
| | | <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> |
| | |
| | | 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']}); |
| | | } |
| | |
| | | $(".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> |