whyclxw
2025-05-28 e16302f9d475c7cc4dd18c5abf1a23cb5502e362
src/main/java/com/whyc/controller/LicenseController.java
@@ -1,22 +1,24 @@
package com.whyc.controller;
import com.whyc.constant.YamlProperties;
import com.whyc.dto.Response;
import com.whyc.encryption.ByteConvertUtil;
import com.whyc.encryption.SM2;
import com.whyc.pojo.License;
import com.whyc.service.LicenseService;
import com.whyc.util.AESUtil;
import com.whyc.util.ActionUtil;
import com.whyc.util.SerialNumberUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.bouncycastle.math.ec.ECPoint;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.ClassUtils;
import org.springframework.web.bind.annotation.GetMapping;
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.bind.annotation.*;
import javax.annotation.Resource;
import java.io.*;
import java.math.BigInteger;
@RequestMapping("license")
@@ -25,6 +27,12 @@
public class LicenseController {
    @Resource
    private LicenseService service;
    /**
     * 类加载时初始化sm2的公私钥
     */
    final static ECPoint publicKey = SM2.getPublicKey();
    final static BigInteger privateKey = SM2.getPrivateKey();
    /**
     * 检验服务器是否注册,是否已存在序列号
@@ -35,6 +43,9 @@
    @GetMapping("/checkRegistered")
    @ApiOperation(value = "校验服务器是否注册")
    public Response checkRegistered(){
        if(YamlProperties.profileType.contains("dev")){
            return new Response().set(1, true);    //测试环境
        }
        return service.checkLicenseExpired();
    }
@@ -56,6 +67,7 @@
        Response model=LicenseController.createLicense(System.currentTimeMillis()+"createTime"+ SerialNumberUtil.getSerialNumber());
        //同时,将序列号生成时间记录到application域中
        //getApplication().setAttribute("serialNumberLicenseTime",System.currentTimeMillis());
        //ActionUtil.getApplication().setAttribute("serialNumberLicenseTime",System.currentTimeMillis());
        return model;
    }
@@ -63,17 +75,22 @@
    public static Response createLicense(String serialNumber){
        //初始化sm2参数x
        SM2 x = new SM2();
        String realPath = ClassUtils.getDefaultClassLoader().getResource("").getPath();
        /*String realPath = ClassUtils.getDefaultClassLoader().getResource("").getPath();
        System.out.println("realPath: "+realPath);
        BigInteger privKey = x.importPrivateKey(realPath+"config/pri_key.ksm");
        ECPoint pubKey = x.importPublicKey(realPath+"config/pub_key.ksm");
        ECPoint pubKey = x.importPublicKey(realPath+"config/pub_key.ksm");*/
        //旧版本
        /*String fileDirName=LicenseController.getRealPath("pub_key.ksm");
        ECPoint pubKey = x.importPublicKey(fileDirName+"/pub_key.ksm");*/
        //System.out.println("pubKey "+pubKey);
        /*String origin = "Company: Fuguang Electronic\n"
                + "Project:BTS monitor platform\n"
                + "Licence type:Permanent";*/
        //获取加密列表
        //System.out.println("origin "+origin);
        byte[] encryptResult = x.encrypt(serialNumber, pubKey);
        //byte[] encryptResult = x.encrypt(serialNumber, pubKey);
        byte[] encryptResult = x.encrypt(serialNumber, publicKey);
        String encrypt = ByteConvertUtil.bytesToHexString(encryptResult);
        //System.out.println("encrypt:"+encrypt);
        return new Response().set(1,encrypt);
@@ -87,75 +104,129 @@
    @ApiOperation(value = "校验license")
    public Response checkSerialNumberLicense(@RequestParam String license){
        Response model = new Response();
        try {
            //获取macid是否一致
            boolean res = false;
            //初始化sm2参数x
            SM2 x = new SM2();
            String realPath = ClassUtils.getDefaultClassLoader().getResource("").getPath();
            BigInteger privKey = x.importPrivateKey(realPath + "config/pri_key.ksm");
            ECPoint pubKey = x.importPublicKey(realPath + "config/pub_key.ksm");
            String origin = "Company: Fuguang Electronic\n"
                    + "Project:BTS monitor platform\n"
                    + "Licence duration:";
            //获取解密后license,附带校验license编码格式
            String decryptResult = null;
            try {
                byte[] bytes = ByteConvertUtil.hexToByteArray(license);
                decryptResult = x.decrypt(bytes, privKey);
            } catch (Exception e) {
                e.printStackTrace();
                model.setMsg("lincense错误");
                return model;
            }
            //用户只能往小调时间
            String[] split1 = decryptResult.split("machineCode:");
            Long registerCodeTime = Long.valueOf(split1[0]);
            Long machineCodeCreateTime = Long.valueOf(split1[1].split("createTime")[0]);
            //检验解码后license的值是否正确
            String serialNumberStr = SerialNumberUtil.getSerialNumber() + "@@" + origin;
            res = decryptResult.contains(serialNumberStr);
            if (res) {
                //校验license输入时间是否超过5分钟,5分钟内则存储到数据库中
                long currentTimeMillis = System.currentTimeMillis();
                //long serialNumberLicenseTime = (long) getApplication().getAttribute("serialNumberLicenseTime");
                //if(currentTimeMillis-serialNumberLicenseTime>=5*60*1000){
                if (currentTimeMillis - machineCodeCreateTime >= 5 * 60 * 1000) {
                    model.setCode(0);
                    model.setMsg("注册码获取及输入超过5分钟,请重新获取注册码");
                } else if (registerCodeTime > currentTimeMillis) {
                    model.setCode(0);
                    model.setMsg("系统时间不正常,请检查");
                } else {
                    model.setCode(1);
                    model.setMsg("注册码校验成功");
                }
                //model.setData(decryptResult);
                //model.setMsgN(serialNumberStr);
                double duration = Integer.parseInt(decryptResult.split("duration:")[1]);
                License data = new License();
                data.setSerialNumber(SerialNumberUtil.getSerialNumber());
                //duration和TimeInUse加密存入数据库
                String durationEncrypt = AESUtil.aesEncrypt(String.valueOf(duration));
                data.setDuration(durationEncrypt);
                String timeInUseEncrypt = AESUtil.aesEncrypt(String.valueOf(0));
                data.setTimeInUse(timeInUseEncrypt);
                //将序列号,有效期 添加入license表
                service.add(data);
        //获取macid是否一致
        boolean res = false;
        //初始化sm2参数x
        SM2 x = new SM2();
        //String realPath = ClassUtils.getDefaultClassLoader().getResource("").getPath();
        //ECPoint pubKey = x.importPublicKey(realPath + "config/pub_key.ksm");
        /*//旧版本
        String fileDirName=LicenseController.getRealPath("pri_key.ksm");
        BigInteger privKey = x.importPrivateKey(fileDirName + "/pri_key.ksm");*/
        String origin = "Company: Fuguang Electronic\n"
                + "Project:BTS monitor platform\n"
                + "Licence duration:";
        //获取解密后license,附带校验license编码格式
        String decryptResult = null;
        byte[] bytes = ByteConvertUtil.hexToByteArray(license);
        decryptResult = x.decrypt(bytes, privateKey);
        //用户只能往小调时间
        String[] split1 = decryptResult.split("machineCode:");
        Long registerCodeTime = Long.valueOf(split1[0]);
        Long machineCodeCreateTime = Long.valueOf(split1[1].split("createTime")[0]);
        //检验解码后license的值是否正确
        String serialNumberStr = SerialNumberUtil.getSerialNumber() + "@@" + origin;
        res = decryptResult.contains(serialNumberStr);
        if (res) {
            //校验license输入时间是否超过5分钟,5分钟内则存储到数据库中
            long currentTimeMillis = System.currentTimeMillis();
            //long serialNumberLicenseTime = (long) getApplication().getAttribute("serialNumberLicenseTime");
            //if(currentTimeMillis-serialNumberLicenseTime>=5*60*1000){
            if (currentTimeMillis - machineCodeCreateTime >= 5 * 60 * 1000) {
                model.setCode(1);
                model.setData(false);
                model.setMsg("注册码获取及输入超过5分钟,请重新获取注册码");
            } else if (registerCodeTime > currentTimeMillis) {
                model.setCode(1);
                model.setData(false);
                model.setMsg("系统时间不正常,请检查");
            } else {
                model.setCode(0);
                model.setMsg("验证失败");
                //model.setData(decryptResult);
                //model.setMsgN(serialNumberStr);
                model.setCode(1);
                model.setData(true);
                model.setMsg("注册码校验成功");
            }
        }catch (Exception e){
            model.setCode(0);
            //model.setData(decryptResult);
            //model.setMsgN(serialNumberStr);
            double duration = Integer.parseInt(decryptResult.split("duration:")[1]);
            License data = new License();
            data.setSerialNumber(SerialNumberUtil.getSerialNumber());
            //duration和TimeInUse加密存入数据库
            String durationEncrypt = AESUtil.aesEncrypt(String.valueOf(duration));
            data.setDuration(durationEncrypt);
            String timeInUseEncrypt = AESUtil.aesEncrypt(String.valueOf(0));
            data.setTimeInUse(timeInUseEncrypt);
            //将序列号,有效期 添加入license表
            service.add(data);
        } else {
            model.setCode(1);
            model.setData(false);
            model.setMsg("验证失败");
            //model.setData(decryptResult);
            //model.setMsgN(serialNumberStr);
        }
       /* model.setCode(1);   //测试环境
        model.setData(true);*/
        return model;
    }
    @PostMapping("/time2DeadLine")
    @ApiOperation(value = "有效期检验")
    public Response time2DeadLine(){
        return service.time2DeadLine();
    }
    //将pri_key.ksm。pub_key.ksm文件拷贝至ksm文件下然后读取fileName:/config/pri_key.ksm
    public static String getRealPath(String fileName){
        //过滤特殊字符,避免路径遍历攻击
        fileName = ActionUtil.filterFileName(fileName);
        ClassPathResource classPathResource = new ClassPathResource("/config/"+fileName);
        InputStream inputStream_pub = null;
        FileOutputStream fos=null;
        ApplicationHome applicationHome = new ApplicationHome(LicenseController.class);
        File jarFile = applicationHome.getDir();
        String fileDirName = jarFile.getParentFile().toString()+ File.separator+"ksm";
        //String fileDirName = jarFile.toString()+File.separator+"ksm";//打包版本
        createFile(fileDirName);//创建文件夹ksm
        try {
            inputStream_pub = classPathResource.getInputStream();
            fos = new FileOutputStream(fileDirName+"/"+fileName);
            byte[] b = new byte[1024];
            int length;
            while((length = inputStream_pub.read(b))>0){
                fos.write(b,0,length);
            }
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(inputStream_pub!=null){
                try {
                    inputStream_pub.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(fos!=null){
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return fileDirName;
    }
    public static void createFile(String pathName) {
        //过滤特殊字符,避免路径遍历攻击
        pathName = ActionUtil.filterFileName(pathName);
        File dir = new File(pathName);
        if (!dir.exists()) {// 判断目录是否存在
            dir.mkdir();
        }
    }
}