1. 通过java keytool 生成私钥库->导出证书->导入到公钥库(注意:linux下由于随机数的问题,私钥库访问密码和公钥库访问密码要相同,私钥密码可以和库密码不一样,密钥格式(必须):字母+数字 长度>=6)

     oo@oo  ~/IdeaProjects/test/LicenseDemo/license/src/main/resources   master ●✚  keytool -genkey -alias privatekey -keysize 1024 -keystore privateKeys.store -validity 3650
    输入密钥库口令: cb0000 
    再次输入新口令: cb0000
    您的名字与姓氏是什么?
      [Unknown]:  caobin
    您的组织单位名称是什么?
      [Unknown]:  caobin
    您的组织名称是什么?
      [Unknown]:  caobin
    您所在的城市或区域名称是什么?
      [Unknown]:  cd
    您所在的省/市/自治区名称是什么?
      [Unknown]:  sc
    该单位的双字母国家/地区代码是什么?
      [Unknown]:  cn
    CN=caobin, OU=caobin, O=caobin, L=cd, ST=sc, C=cn是否正确?
      [否]:  y
    
    输入 <privatekey> 的密钥口令 注意:所有私钥可以设置为一样,但是不要和私钥库密码一样!
            (如果和密钥库口令相同, 按回车):  cb9999
    再次输入新口令: cb9999
    
    Warning:
    JKS 密钥库使用专用格式。建议使用 "keytool -importkeystore -srckeystore privateKeys.store -destkeystore privateKeys.store -deststoretype pkcs12" 迁移到行业标准格式 PKCS12。
     oo@oo  ~/IdeaProjects/test/LicenseDemo/license/src/main/resources   master ●✚  keytool -export -alias privatekey -file certfile.cer -keystore privateKeys.store          
    输入密钥库口令:  cb0000
    存储在文件 <certfile.cer> 中的证书
    
    Warning:
    JKS 密钥库使用专用格式。建议使用 "keytool -importkeystore -srckeystore privateKeys.store -destkeystore privateKeys.store -deststoretype pkcs12" 迁移到行业标准格式 PKCS12。
     oo@oo  ~/IdeaProjects/test/LicenseDemo/license/src/main/resources   master ●✚  keytool -import -alias publiccert -file certfile.cer -keystore publicCerts.store          
    输入密钥库口令:  cb0000
    再次输入新口令: cb0000
    所有者: CN=caobin, OU=caobin, O=caobin, L=cd, ST=sc, C=cn
    发布者: CN=caobin, OU=caobin, O=caobin, L=cd, ST=sc, C=cn
    序列号: b0f76e6
    有效期为 Wed Sep 30 14:25:19 CST 2020 至 Sat Sep 28 14:25:19 CST 2030
    证书指纹:
             MD5:  9C:EC:2A:B6:4E:14:25:18:B7:71:69:BE:62:1E:26:8C
             SHA1: 7F:69:FA:54:C6:AC:40:9B:96:BF:BE:22:F4:BC:B2:A6:3F:70:E2:BB
             SHA256: 9A:EB:7A:59:6F:78:02:E8:2B:B7:8F:79:CF:77:09:4B:9A:F7:73:6A:37:B0:D0:8E:15:78:1C:A1:04:CF:CA:AF
    签名算法名称: SHA256withDSA
    主体公共密钥算法: 1024 位 DSA 密钥
    版本: 3
    
    扩展: 
    
    #1: ObjectId: 2.5.29.14 Criticality=false
    SubjectKeyIdentifier [
    KeyIdentifier [
    0000: 59 01 47 4F 9E EF 56 A6   93 5E 68 59 32 E9 AA 19  Y.GO..V..^hY2...
    0010: 9A 59 E6 06                                        .Y..
    ]
    ]
    
    是否信任此证书? [否]:  y
    证书已添加到密钥库中
    
  2. 创建 校验 license代码

    		<!-- License -->
    		<dependency>
    			<groupId>de.schlichtherle.truelicense</groupId>
    			<artifactId>truelicense-core</artifactId>
    			<version>1.33</version>
    		</dependency>
    import de.schlichtherle.license.LicenseManager;
    import de.schlichtherle.license.LicenseParam;
    
    public class LicenseManagerHolder {
    
        private static volatile LicenseManager licenseManager = null;
    
        private LicenseManagerHolder() {
        }
    
        public static LicenseManager getLicenseManager(LicenseParam param) {
            if (licenseManager == null) {
                synchronized (LicenseManagerHolder.class) {
                    if (licenseManager == null) {
                        licenseManager = new LicenseManager(param);
                    }
                }
            }
            return licenseManager;
        }
    }
    import java.net.InetAddress;
    import java.net.NetworkInterface;
    import java.net.SocketException;
    import java.util.ArrayList;
    import java.util.Enumeration;
    import java.util.List;
    import java.util.stream.Collectors;
    
    /**
     * 用于获取客户Linux服务器的基本信息
     */
    public class LinuxServerInfos{
    
        protected List<String> getIpAddress() throws Exception {
            List<String> result = null;
    
            //获取所有网络接口
            List<InetAddress> inetAddresses = getLocalAllInetAddress();
    
            if(inetAddresses != null && inetAddresses.size() > 0){
                result = inetAddresses.stream().map(InetAddress::getHostAddress).distinct().map(String::toLowerCase).collect(Collectors.toList());
            }
    
            return result;
        }
    
    
        /**
         * 获取某个网络接口的Mac地址
         */
        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;
        }
    
        public 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;
        }
    
    
        private 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;
        }
    }
    
    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.io.IOException;
    import java.io.InputStream;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Properties;
    import java.util.prefs.Preferences;
    
    public class CreateLicense {
        private static Logger log = LogManager.getLogger(CreateLicense.class);
    
        /**
         * X500Princal 是一个证书文件的固有格式,详见API
         */
        private final static X500Principal DEFAULT_HOLDERAND_ISSUER = new X500Principal("CN=Duke, OU=JavaSoft, O=Sun Microsystems, C=US");
    
        private String priAlias;
        private String privateKeyPwd;
        private String keyStorePwd;
        private String subject;
        private String priPath;
    
        private String issued;
        private String notBefore;
        private String notAfter;
        private String ipAddress;
        private String macAddress;
        private String userNumber;
        private String consumerType;
        private int consumerAmount;
        private String info;
    
        private String licPath;
    
    
        /**
         * 构造器,参数初始化
         *
         * @param confPath 参数配置文件路径
         */
        public CreateLicense(String confPath) {
            // 获取参数
            Properties prop = new Properties();
            try (InputStream in = getClass().getResourceAsStream(confPath)) {
                prop.load(in);
            } catch (IOException e) {
                log.error("CreateLicense Properties load inputStream error.", e);
            }
            //common param
            priAlias = prop.getProperty("private.key.alias");
            privateKeyPwd = prop.getProperty("private.key.pwd");
            keyStorePwd = prop.getProperty("key.store.pwd");
            subject = prop.getProperty("subject");
            priPath = prop.getProperty("priPath");
            // license content
            issued = prop.getProperty("issuedTime");
            notBefore = prop.getProperty("notBefore");
            notAfter = prop.getProperty("notAfter");
            ipAddress = prop.getProperty("ipAddress");
            macAddress = prop.getProperty("macAddress");
            userNumber = prop.getProperty("userNumber");
            consumerType = prop.getProperty("consumerType");
            consumerAmount = Integer.valueOf(prop.getProperty("consumerAmount"));
            info = prop.getProperty("info");
    
            licPath = prop.getProperty("licPath");
        }
    
    
        /**
         * 生成证书,在证书发布者端执行
         *
         * @throws Exception
         */
        public void create() throws Exception {
            LicenseManager licenseManager = LicenseManagerHolder.getLicenseManager(initLicenseParams());
            licenseManager.store(buildLicenseContent(), new File(licPath));
            log.info("------ 证书发布成功 ------");
        }
    
        /**
         * 初始化证书的相关参数
         *
         * @return
         */
        private LicenseParam initLicenseParams() {
            Class<CreateLicense> clazz = CreateLicense.class;
            Preferences preferences = Preferences.userNodeForPackage(clazz);
            // 设置对证书内容加密的对称密码
            CipherParam cipherParam = new DefaultCipherParam(keyStorePwd);
            // 参数 1,2 从哪个Class.getResource()获得密钥库;
            // 参数 3 密钥库的别名;
            // 参数 4 密钥库存储密码;
            // 参数 5 密钥库密码
            KeyStoreParam privateStoreParam = new DefaultKeyStoreParam(clazz, priPath, priAlias, keyStorePwd, privateKeyPwd);
            // 返回生成证书时需要的参数
            return new DefaultLicenseParam(subject, preferences, privateStoreParam, cipherParam);
        }
    
        /**
         * 通过外部配置文件构建证书的的相关信息
         *
         * @return
         * @throws ParseException
         */
        public LicenseContent buildLicenseContent() throws ParseException {
            LicenseContent content = new LicenseContent();
            SimpleDateFormat formate = new SimpleDateFormat("yyyy-MM-dd");
            content.setConsumerAmount(consumerAmount);
            content.setConsumerType(consumerType);
            content.setHolder(DEFAULT_HOLDERAND_ISSUER);
            content.setIssuer(DEFAULT_HOLDERAND_ISSUER);
            content.setIssued(formate.parse(issued));
            content.setNotBefore(formate.parse(notBefore));
            content.setNotAfter(formate.parse(notAfter));
            content.setInfo(info);
            // 扩展字段
            Map<String, String> map = new HashMap<>(4);
            map.put("ip", ipAddress);
            map.put("mac", macAddress);
            map.put("userNumber", userNumber);
            content.setExtra(map);
            return content;
        }
    
        public static void main(String[] args) throws Exception {
            CreateLicense clicense = new CreateLicense("/licenseCreateParam.properties");
            clicense.create();
        }
    }
    import de.schlichtherle.license.*;
    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    
    import java.io.File;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.InetAddress;
    import java.net.NetworkInterface;
    import java.net.SocketException;
    import java.text.DateFormat;
    import java.text.SimpleDateFormat;
    import java.time.Instant;
    import java.time.LocalDate;
    import java.time.LocalDateTime;
    import java.time.ZoneId;
    import java.time.format.DateTimeFormatter;
    import java.util.*;
    import java.util.prefs.Preferences;
    
    public class VerifyLicense {
        private static Logger log = LogManager.getLogger(VerifyLicense.class);
    
    
        private String pubAlias;
        private String keyStorePwd;
        private String subject;
        private String licDir;
        private String pubPath;
    
        public VerifyLicense() {
            // 取默认配置
            setConf("/licenseVerifyParam.properties");
        }
    
        public VerifyLicense(String confPath) {
            setConf(confPath);
        }
    
        /**
         * 通过外部配置文件获取配置信息
         *
         * @param confPath 配置文件路径
         */
        private void setConf(String confPath) {
            // 获取参数
            Properties prop = new Properties();
            InputStream in = getClass().getResourceAsStream(confPath);
            try {
                prop.load(in);
            } catch (IOException e) {
                log.error("VerifyLicense Properties load inputStream error.", e);
            }
            this.subject = prop.getProperty("subject");
            this.pubAlias = prop.getProperty("public.alias");
            this.keyStorePwd = prop.getProperty("key.store.pwd");
            this.licDir = prop.getProperty("license.dir");
            this.pubPath = prop.getProperty("public.store.path");
        }
    
        /**
         * 安装证书证书
         */
        public void install() {
            try {
                LicenseManager licenseManager = getLicenseManager();
                licenseManager.install(new File(licDir));
                log.info("安装证书成功!");
            } catch (Exception e) {
                log.error("安装证书失败!", e);
                Runtime.getRuntime().halt(1);
            }
    
        }
    
        private LicenseManager getLicenseManager() {
            return LicenseManagerHolder.getLicenseManager(initLicenseParams());
        }
    
        /**
         * 初始化证书的相关参数
         */
        private LicenseParam initLicenseParams() {
            Class<VerifyLicense> clazz = VerifyLicense.class;
            Preferences pre = Preferences.userNodeForPackage(clazz);
            CipherParam cipherParam = new DefaultCipherParam(keyStorePwd);
            KeyStoreParam pubStoreParam = new DefaultKeyStoreParam(clazz, pubPath, pubAlias, keyStorePwd, null);
            return new DefaultLicenseParam(subject, pre, pubStoreParam, cipherParam);
        }
    
        /**
         * 验证证书的合法性
         */
        public boolean vertify() {
            try {
                LicenseManager licenseManager = getLicenseManager();
                LicenseContent verify = licenseManager.verify();
                log.info("验证证书成功!");
                Map<String, String> extra = (Map) verify.getExtra();
                System.out.println("license map:"+extra);
                String licenseIpString = extra.get("ip");//ip1,ip2,ip3
                String licenseMacString = extra.get("mac");//mac1,mac2,mac3
                DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                Date notAfter = verify.getNotAfter();
                Date notBefore = verify.getNotBefore();
                Instant notBeforeInstant = notBefore.toInstant();
                Instant notAfterInstant = notAfter.toInstant();
                ZoneId zoneId = ZoneId.systemDefault();
    
                LocalDate startTime = notBeforeInstant.atZone(zoneId).toLocalDate();
                LocalDate endTime = notAfterInstant.atZone(zoneId).toLocalDate();
                Integer licenseUserNumber = Integer.valueOf(extra.get("userNumber"));
    
                LinuxServerInfos serverinfos =new LinuxServerInfos();
    
                //校验时间
                LocalDate now = LocalDate.now();
                if (!(now.isAfter(startTime) && now.isBefore(endTime))) {
                    log.error("有效期 验证不通过");
                }
                if (!(serverinfos.getIpAddress().stream().anyMatch(ip-> Arrays.asList(licenseIpString.split(",")).stream().anyMatch(licenseIp-> licenseIp.equalsIgnoreCase(ip))))){
                    log.error("IP 验证不通过");
                    return false;
                }
                if (!(serverinfos.getMacAddress().stream().anyMatch(mac-> Arrays.asList(licenseMacString.split(",")).stream().anyMatch(licenseMac-> licenseMac.equalsIgnoreCase(mac))))){
                    log.error("MAC 验证不通过");
                    return false;
                }
                //todo 获取服务器当前user表用户数量
                Integer serverUserNumber=11;
                if (serverUserNumber>licenseUserNumber){
                    log.error("User Number 验证不通过");
                    return false;
                }
    
                log.info("IP、MAC、用户数量 验证通过");
                return true;
            } catch (LicenseContentException ex) {
                log.error("证书已经过期!", ex);
                return false;
            } catch (Exception e) {
                log.error("验证证书失败!", e);
                return false;
            }
        }
    
        /**
         * 得到本机 mac 地址
         *
         * @param inetAddress
         * @throws SocketException
         */
        private String getLocalMac(InetAddress inetAddress) throws SocketException {
            //获取网卡,获取地址
            byte[] mac = NetworkInterface.getByInetAddress(inetAddress).getHardwareAddress();
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < mac.length; i++) {
                if (i != 0) {
                    sb.append("-");
                }
                //字节转换为整数
                int temp = mac[i] & 0xff;
                String str = Integer.toHexString(temp);
                if (str.length() == 1) {
                    sb.append("0" + str);
                } else {
                    sb.append(str);
                }
            }
            return sb.toString().toUpperCase();
        }
    
        public static void main(String[] args) {
            VerifyLicense vlicense = new VerifyLicense();
            vlicense.install();
            if (!vlicense.vertify()) {
                Runtime.getRuntime().halt(1);
            }
        }
    }
    
    package com.ruoyi.web.controller.license;
    
    import de.schlichtherle.license.*;
    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    import org.springframework.scheduling.annotation.Scheduled;
    import org.springframework.stereotype.Component;
    
    import javax.annotation.PostConstruct;
    import java.io.File;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.InetAddress;
    import java.net.NetworkInterface;
    import java.net.SocketException;
    import java.time.Instant;
    import java.time.LocalDate;
    import java.time.ZoneId;
    import java.time.format.DateTimeFormatter;
    import java.util.Arrays;
    import java.util.Date;
    import java.util.Map;
    import java.util.Properties;
    import java.util.prefs.Preferences;
    
    @Component
    public class VerifyLicense {
        private static Logger log = LogManager.getLogger(VerifyLicense.class);
    
    
        private String pubAlias;
        private String keyStorePwd;
        private String subject;
        private String licDir;
        private String pubPath;
    
        public VerifyLicense() {
            // 取默认配置
            setConf("/licenseVerifyParam.properties");
        }
    
        public VerifyLicense(String confPath) {
            setConf(confPath);
        }
    
        /**
         * 通过外部配置文件获取配置信息
         *
         * @param confPath 配置文件路径
         */
        private void setConf(String confPath) {
            // 获取参数
            Properties prop = new Properties();
            InputStream in = getClass().getResourceAsStream(confPath);
            try {
                prop.load(in);
            } catch (IOException e) {
                log.error("VerifyLicense Properties load inputStream error.", e);
            }
            this.subject = prop.getProperty("subject");
            this.pubAlias = prop.getProperty("public.alias");
            this.keyStorePwd = prop.getProperty("key.store.pwd");
            this.licDir = prop.getProperty("license.dir");
            this.pubPath = prop.getProperty("public.store.path");
        }
    
        /**
         * 安装证书证书
         */
        public void install() {
            try {
                LicenseManager licenseManager = getLicenseManager();
                licenseManager.install(new File(licDir));
                log.info("安装证书成功!");
            } catch (Exception e) {
                log.error("安装证书失败!", e);
                Runtime.getRuntime().halt(1);
            }
    
        }
    
        private LicenseManager getLicenseManager() {
            return LicenseManagerHolder.getLicenseManager(initLicenseParams());
        }
    
        /**
         * 初始化证书的相关参数
         */
        private LicenseParam initLicenseParams() {
            Class<VerifyLicense> clazz = VerifyLicense.class;
            Preferences pre = Preferences.userNodeForPackage(clazz);
            CipherParam cipherParam = new DefaultCipherParam(keyStorePwd);
            KeyStoreParam pubStoreParam = new DefaultKeyStoreParam(clazz, pubPath, pubAlias, keyStorePwd, null);
            return new DefaultLicenseParam(subject, pre, pubStoreParam, cipherParam);
        }
    
        /**
         * 验证证书的合法性
         */
        public boolean vertify() {
            try {
                LicenseManager licenseManager = getLicenseManager();
                LicenseContent verify = licenseManager.verify();
                log.info("验证证书成功!");
                Map<String, String> extra = (Map) verify.getExtra();
                //System.out.println("license map:"+extra);
                String licenseIpString = extra.get("ip");//ip1,ip2,ip3
                String licenseMacString = extra.get("mac");//mac1,mac2,mac3
                DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                Date notAfter = verify.getNotAfter();
                Date notBefore = verify.getNotBefore();
                Instant notBeforeInstant = notBefore.toInstant();
                Instant notAfterInstant = notAfter.toInstant();
                ZoneId zoneId = ZoneId.systemDefault();
    
                LocalDate startTime = notBeforeInstant.atZone(zoneId).toLocalDate();
                LocalDate endTime = notAfterInstant.atZone(zoneId).toLocalDate();
                Integer licenseUserNumber = Integer.valueOf(extra.get("userNumber"));
    
                LinuxServerInfos serverinfos =new LinuxServerInfos();
    
                //校验时间
                LocalDate now = LocalDate.now();
                if (!(now.isAfter(startTime) && now.isBefore(endTime))) {
                    log.error("有效期 验证不通过");
                }
                if (!(serverinfos.getIpAddress().stream().anyMatch(ip-> Arrays.asList(licenseIpString.split(",")).stream().anyMatch(licenseIp-> licenseIp.equalsIgnoreCase(ip))))){
                    log.error("IP 验证不通过");
                    return false;
                }
                if (!(serverinfos.getMacAddress().stream().anyMatch(mac-> Arrays.asList(licenseMacString.split(",")).stream().anyMatch(licenseMac-> licenseMac.equalsIgnoreCase(mac))))){
                    log.error("MAC 验证不通过");
                    return false;
                }
                //todo 获取服务器当前user表用户数量
                Integer serverUserNumber=10;
                if (serverUserNumber>licenseUserNumber){
                    log.error("User Number 验证不通过");
                    return false;
                }
    
                log.info("IP、MAC、用户数量 验证通过");
                return true;
            } catch (LicenseContentException ex) {
                log.error("证书已经过期!", ex);
                return false;
            } catch (Exception e) {
                log.error("验证证书失败!", e);
                return false;
            }
        }
    
        /**
         * 得到本机 mac 地址
         *
         * @param inetAddress
         * @throws SocketException
         */
        private String getLocalMac(InetAddress inetAddress) throws SocketException {
            //获取网卡,获取地址
            byte[] mac = NetworkInterface.getByInetAddress(inetAddress).getHardwareAddress();
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < mac.length; i++) {
                if (i != 0) {
                    sb.append("-");
                }
                //字节转换为整数
                int temp = mac[i] & 0xff;
                String str = Integer.toHexString(temp);
                if (str.length() == 1) {
                    sb.append("0" + str);
                } else {
                    sb.append(str);
                }
            }
            return sb.toString().toUpperCase();
        }
    
        @PostConstruct
        public void installLicense() {
            install();
        }
    
        //{秒数} {分钟} {小时} {日期} {月份} {星期} {年份(可为空)}
        //每天1点1分1秒执行1次
        //需要在application启动类上开启@EnableScheduling 
        @Scheduled(cron = "1 1 1 * * ?")
        public void vertifyLicense() {
            boolean vertifyResult = vertify();
            if (!vertifyResult) {
                Runtime.getRuntime().halt(1);
            }
        }
    }
  3. 配置信息

    ########## 私钥的配置信息 ###########
    # 私钥的别名
    private.key.alias=privatekey
    # privateKeyPwd(该密码是生成密钥对的密码 — 需要妥善保管,不能让使用者知道)
    private.key.pwd=cb9999
    # keyStorePwd(该密码是访问密钥库的密码 — 使用 keytool 生成密钥对时设置,使用者知道该密码)
    key.store.pwd=cb0000
    # 项目的唯一识别码
    subject=caobin
    # 密钥库的地址(放在 resource 目录下)
    priPath=/privateKeys.store
    
    ########## license content ###########
    # 发布日期
    issuedTime=2019-09-12
    # 有效开始日期
    notBefore=2019-09-12
    # 有效截止日期
    notAfter=2029-12-30
    # ip 地址
    ipAddress=192.168.22.55
    # mac 地址
    macAddress=9C-B6-D0-BC-05-C9
    #用户数量
    userNumber=10
    # 使用者类型,用户(user)、电脑(computer)、其他(else)
    consumerType=user
    # 证书允许使用的消费者数量
    consumerAmount=1
    # 证书说明
    info=power by caobin
    
    
    #生成证书的地址
    licPath=/home/oo/IdeaProjects/test/LicenseDemo/license/src/main/resources/license.lic
    
    
    ########## 公钥的配置信息 ###########
    # 公钥别名
    public.alias=publiccert
    # 该密码是访问密钥库的密码 — 使用 keytool 生成密钥对时设置,使用者知道该密码
    key.store.pwd=cb0000
    # 项目的唯一识别码 — 和私钥的 subject 保持一致
    subject = caobin
    # 证书路径(我这边配置在了 linux 根路径下,即 /license.lic )
    license.dir=/home/oo/IdeaProjects/test/LicenseDemo/license/src/main/resources/license.lic
    # 公共库路径(放在 resource 目录下)
    public.store.path=/publicCerts.store
  4. 项目文件 license