第一步:我们可以通过Jdk(建议jdk1.8)自带的keytool工具生成,进入JDK的bin目录命令行(win+r输入cmd)输入以下命令:

1. 生成命令

keytool -genkeypair -keysize 1024 -validity 3650 -alias "privateKey" 
-keystore "privateKeys.keystore" -storepass "public_password1234" -keypass 
"private_password1234" -dname "CN=localhost, OU=localhost, O=localhost, L=SH, ST=SH, C=CN"

参数说明

  1. keysize 密钥长度
  2. validity 私钥的有效期(单位:天)
  3. alias 私钥别称
  4. keystore 指定私钥库文件的名称 (生成在当前目录)
  5. storepass 指定私钥库的密码 (keystore 文件存储密码)
  6. keypass 指定别名条目的密码 (私钥加解密密码)
  7. dname 证书个人信息
    CN 为你的姓名
    OU 为你的组织单位名称
    O 为你的组织名称
    L 为你所在的城市名称
    ST 为你所在的省份名称
    C 为你的国家名称

生成文件如下图所示
在这里插入图片描述

2. 执行导出命令

keytool -import -alias "publicCert" -file "certfile.cer" -keystore "publicCerts.keystore"
 -storepass "public_password1234"

参数说明:

  1. alias 公钥别称
  2. file 证书文件名称
  3. keystore 公钥文件名称
  4. storepass 指定私钥库的密码

3. 执行导入命令

keytool -import -alias "publicCert" -file "certfile.cer" -keystore "publicCerts.keystore" -storepass "public_password1234"

命令行当前路径可以看到以下三个文件:

①privateKeys.keystore(私钥)提供给生成证书使用 (生成后放在license生成项目的文件夹中,如放在部署路径的resource/key文件夹)
在这里插入图片描述

②publicCerts. keystore(公钥)提供给证书认证使用(要跟随部署文件一块放到部署服务器,如放在部署路径的resource/default 文件夹) 。
在这里插入图片描述

③certfile.cer后续步骤用不到,可以删除

第二步 生成许可证

旧版license证书生成地址: http://192.168.16.212:7000/createLicense (不带平台标识)

项目位置在文件服务器: \192.168.16.114\v3.0产品相关资源\05 预研\License证书
在这里插入图片描述
代码结构如下图所示:
在这里插入图片描述

其中yq_privateKeys.keystore 是在第一步生成的。
license配置

license.keyPass=a123456 
license.storePass=a123456
license.licensePath=${user.dir}/resource/key/yq_license.lic #license证书 生成路径
license.privateKeysStorePath=${user.dir}/resource/key/yq_privateKeys.keystore # 私钥的存放路径

其中 1. license.keyPass 和license.storePass 要个第一步使用的一致。

第三步 校验许可证

在这里插入图片描述
license的公钥安放位置如下图所示。
在这里插入图片描述
安装路径为如下配置

license:
  subject: yq_license
  publicAlias: publicCert
  storePass: a123456
  licensePath: ${user.dir}/resource/default/yq_license.lic
  publicKeysStorePath: ${user.dir}/resource/default/yq_publicCerts.keystore

subject :证书名
publicAlias:公钥别称
storePass:公钥密码
licensePath:证书文职
publicKeysStorePath:公钥位置

前端相关接口

  1. /license/importLicense 证书上传
  2. /license/installLicense 证书安装
  3. /license/licenseTest 证书校验
    注: 以上三接口需要在shiro中配置放开token校验

license校验代码如下:

@GetMapping(value = "/licenseTest")
    public Result<?> test() {
        LicenseContent licenseContent = this.getLicenseContent();
        try {
            if ("证书合法".equals(customLicenseManager.validateCreate(licenseContent))) {
                return Result.ok(customLicenseManager.validateCreate(licenseContent));
            } else {
                return Result.error(customLicenseManager.validateCreate(licenseContent));
            }
        } catch (Exception e) {
            if ("exc.licenseHasExpired".equals(this.getMessage())) {
                return Result.error("许可证已过期,请重新上传");
            } else {
                return Result.error(this.getMessage());
            }
        }
    }
/**
     * 校验生成证书的参数信息
     *
     * @param content 证书正文
     */
    public String validateCreate(LicenseContent content) throws LicenseContentException {
        final LicenseParam param = getLicenseParam();
        final Date now = new Date();
        final Date notBefore = content.getNotBefore();
        final Date notAfter = content.getNotAfter();
        final String consumerType = content.getConsumerType();
        if (null != notAfter && now.after(notAfter)) {
            System.out.println("证书失效时间不能早于当前时间");
            // throw new LicenseContentException("证书失效时间不能早于当前时间");
            return "证书已失效,请重新上传";
        } else if (null != notBefore && null != notAfter && notAfter.before(notBefore)) {
            System.out.println("证书生效时间不能晚于证书失效时间");
            //  throw new LicenseContentException("证书生效时间不能晚于证书失效时间");
            return "证书生效时间不能晚于证书失效时间";
        } else if (null == consumerType) {
            System.out.println("用户类型不能为空");
            //  throw new LicenseContentException("用户类型不能为空");
            return "用户类型不能为空";
        }
        return "证书合法";


    }
    /**
     * 安装License证书
     */
    public synchronized LicenseContent install(LicenseVerifyParam param) throws Exception {
        LicenseContent result = null;
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        //获取继承了LicenseManager的CustomLicenseManager的单例对象 在这里调用验证方法
        LicenseManager licenseManager = LicenseManagerHolder.getInstance(initLicenseParam(param));

        //1. 卸载历史证书
        licenseManager.uninstall();

        //2. 安装新的证书
        File file = new File(param.getLicensePath());
        //logger.info("授权证书安装路径 :" + file.getPath());

        //此处调用 CustomLicenseManager.install(),通过重写后的方法在安装时进行部分校验
        result = licenseManager.install(file);

        //logger.info(MessageFormat.format("证书安装成功,证书有效期:{0} - {1}", format.format(result.getNotBefore()), format.format(result.getNotAfter())));

        return result;
    }
 @Override
    protected synchronized void validate(final LicenseContent content) throws LicenseContentException {
        RedisTemplate redisTemplate = (RedisTemplate) SpringContextUtils.getBean("redisTemplate");

        //1. 首先调用父类的validate方法
        super.validate(content);

        //2. 然后校验自定义的License参数
        //License中可被允许的参数信息
        LicenseCheckModel expectedCheckModel = (LicenseCheckModel) content.getExtra();
        logger.info("expectedCheckModel====="+expectedCheckModel);

        //从缓存中获取当前服务器真实的参数信息
        LocalCacheUtils cacheUtils = LocalCacheUtils.getInstance();
        LicenseCheckModel serverCheckModel = (LicenseCheckModel) cacheUtils.getValueByKey("serverInfo");
        logger.info("serverCheckModel==="+serverCheckModel);

        if (expectedCheckModel != null && serverCheckModel != null) {
            //针对同一证书只在首次安装时校验安装时间
            final Date now = new Date();
            final Date installedExpiration = expectedCheckModel.getInstalledExpiration();
            //判断此前是否已记录证书标识 以及 当前证书标识与此前纪录的证书标识的值是否一致
            String currentLicenseCode = String.valueOf(redisTemplate.opsForValue().get("license_currentLicense"));
            if (redisTemplate.hasKey("license_redisLicense")) {
                String redisLicenseCode = String.valueOf(redisTemplate.opsForValue().get("license_redisLicense"));
                if (!redisLicenseCode.equals(currentLicenseCode)) {
                    if (null != installedExpiration && now.after(installedExpiration)) {
                        throw new LicenseContentException("当前时间不能晚于安装截止时间");
                    }
                }
            } else {
                if (null != installedExpiration && now.after(installedExpiration)) {
                    throw new LicenseContentException("当前时间不能晚于安装截止时间");
                }
            }

            //授权要求IP、Mac、Sn校验值至少存在一个 且 该校验值需通过校验
            if (CollectionUtils.isNotEmpty(expectedCheckModel.getIpAddress()) || CollectionUtils.isNotEmpty(expectedCheckModel.getMacAddress()) || CollectionUtils.isNotEmpty(expectedCheckModel.getMainBoardSerial())) {
                //校验IP
                boolean checkIpAddress = checkIpAddress(expectedCheckModel.getIpAddress(), serverCheckModel.getIpAddress());
                //校验Mac
                boolean checkMacAddressPre = checkMacAddressPre(expectedCheckModel.getMacAddress());
                boolean checkMacAddress = checkIpAddress(expectedCheckModel.getMacAddress(), serverCheckModel.getMacAddress());
                //校验MainBoardSerial
                boolean checkMainBoardSerial = checkIpAddress(expectedCheckModel.getMainBoardSerial(), serverCheckModel.getMainBoardSerial());
                if (!(checkIpAddress && (checkMacAddress || checkMacAddressPre) && checkMainBoardSerial)) {
                    throw new LicenseContentException("IP、Mac或Sn不符合授权要求");
                }
            } else {
                throw new LicenseContentException("IP、Mac或Sn不符合授权要求");
            }

            //校验平台标识
            if (StringUtils.isNotEmpty(expectedCheckModel.getPlatformIdentify()) && !expectedCheckModel.getPlatformIdentify().equals("sdyq-2019-yqsm-product-1.0")) {
                throw new LicenseContentException("产品标识不符合授权要求");
            }

            //校验CPU序列号
            if (!checkIpAddress(expectedCheckModel.getCpuSerial(), serverCheckModel.getCpuSerial())) {
                throw new LicenseContentException("当前服务器的CPU序列号没在授权范围内");
            }

            //校验CPU个数
            if (!checkCpus(expectedCheckModel.getCpus(), serverCheckModel.getCpus())) {
                throw new LicenseContentException("当前服务器的CPU数量没在授权范围内");
            }
        } else {
            throw new LicenseContentException("不能获取服务器硬件信息");
        }
    }
Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐