TrueLicense实现产品License验证

本文介绍了如何使用TrueLicense作为开源证书管理引擎,为Java软件产品添加试用期授权功能。通过生成密钥对、创建证书并进行本地验证,详细阐述了License授权机制的原理,以及Springboot集成TrueLicense的证书生成和认证过程。
摘要由CSDN通过智能技术生成

技术:apache-maven-3.3.9 +jdk1.8.0_102
运行环境:ideaIC-2020.1.3 + apache-maven-3.3.9+ jdk1.8.0_102

家精品内容,核心代码解析
多代码预警~觉着有帮助的别忘了给小普点赞!
作者:陈鸿姣 编辑:Carol

01 概述

TrueLicense是一个开源的证书管理引擎,使用trueLicense来做软件产品的保护,基于TrueLicense实现产品License验证功能,给产品加上License验证功能,进行试用期授权,在试用期过后,产品不再可用。

02 使用场景
小普看来,当项目交付给客户之后用签名来保证客户不能随意使用项目,TrueLicense默认校验了开始结束时间,可扩展增加mac地址校验等。

因此,小普详细介绍的是本地校验 license授权机制的原理以及主要使用TrueLicense的LicenseManager类来生成证书文件、安装证书文件、验证证书文件等。

03 license授权机制的原理
原理如下:
(1)生成密钥对,包含私钥和公钥。(2)授权者保留私钥,使用私钥对授权信息诸如使用截止日期,mac 地址等内容生成 license 签名证书。(3)公钥给使用者,放在代码中使用,用于验证 license 签名证书是否符合使用条件。

04 使用KeyTool生成密匙库
使用jdk自带的KeyTool工具生成密钥库,这里使用的jdk版本是jdk1.8.0_102。首先我们找到KeyTool所在的目录,截图如下:
在这里插入图片描述
可以看到Windowscmd窗口如下:
在这里插入图片描述
生成密码库的步骤如下:
在这里插入图片描述
(1)生成密钥库

keytool -genkeypair-keysize 1024 -validity 3650-alias 
"privateKey" -keystore "privateKeys.keystore"

在这里插入图片描述
(2)生成证书文件

keytool -exportcert -alias "privateKey" -keystore "privateKeys.keystore" -
file "certfile.cer"

在这里插入图片描述
(3)生成公钥库

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

在这里插入图片描述
在这里插入图片描述
最后在D:\work soft\java\jdk1.8.0_102\jre\bin目录下:看到以下三个文件:

privateKeys.keystore(私钥)提供给生成证书使用
publicCerts. keystore(公钥)提供给证书认证使用
certfile.cer后续步骤用不到,可以删除。
05 Springboot+TrueLicense证书生成和认证

(1)引入jar包:

首先,我们需要引入 truelicense 的 jar 包,用于实现我们的证书管理。

在这里插入图片描述
(2)证书生成步骤以及核心实现代码

① 校验自定义的License参数。首先,创建自定义的可被允许的服务器硬件信息的实体类(如果校验其他参数,可自行补充).备注:如果只需要检验文件的生效和过期时间无需创建此类。

/**
 * @author chenhongjiao
 */
@Data
public class LicenseCheckModelimplements Serializable {
    private static final long serialVersionUID = 8600137500316662317L;
    /**
     * 可被允许的IP地址
     */
    private List<String> ipAddress;

    /**
     * 可被允许的MAC地址
     */
    private List<String> macAddress;

    /**
     * 可被允许的CPU序列号
     */
    private String cpuSerial;

    /**
     * 可被允许的主板序列号
     */
    private String mainBoardSerial;

}

② 其次,创建License生成需要的参数实体类

/**
 * @author chenhongjiao
 */
@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 LicenseCheckModel licenseCheckModel;
}

③添加抽象类AbstractServerInfos,用户获取服务器的硬件信息。
(备注:根据需要选择,无需额外校验可去掉)
@Slf4j
public abstract class AbstractServerInfos {

/**
 * 组装需要额外校验的License参数
 * @author chenhongjiao
 * @date 2021/03/26 14:23
 * @since 1.0.0
 * @return LicenseCheckModel
 */
public LicenseCheckModel getServerInfos(){
    LicenseCheckModel result = new LicenseCheckModel();

    try {
        result.setIpAddress(this.getIpAddress());
        result.setMacAddress(this.getMacAddress());
        result.setCpuSerial(this.getCPUSerial());
        result.setMainBoardSerial(this.getMainBoardSerial());
    }catch (Exception e){
        log.error("获取服务器硬件信息失败",e);
    }

    return result;
}

/**
 * 获取IP地址
 * @author chenhongjiao
 * @date 2021/03/26 11:32
 * @since 1.0.0
 * @return java.util.List<java.lang.String>
 */
protected abstract List<String> getIpAddress() throws Exception;

/**
 * 获取Mac地址
 * @author chenhongjiao
 * @date 2021/03/26 11:32
 * @since 1.0.0
 * @return java.util.List<java.lang.String>
 */
protected abstract List<String> getMacAddress() throws Exception;

/**
 * 获取CPU序列号
 * @author chenhongjiao
 * @date 2021/03/26 11:35
 * @since 1.0.0
 * @return java.lang.String
 */
protected abstract String getCPUSerial() throws Exception;

/**
 * 获取主板序列号
 * @author chenhongjiao
 * @date 2021/03/26 11:35
 * @since 1.0.0
 * @return java.lang.String
 */
protected abstract String getMainBoardSerial() throws Exception;

/**
 * 获取当前服务器所有符合条件的InetAddress
 * @author chenhongjiao
 * @date 2021/03/26 17:38
 * @since 1.0.0
 * @return java.util.List<java.net.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.isLinkLocalAddress() && !inetAddr.isMulticastAddress()){
                result.add(inetAddr);
            }
        }
    }

    return result;
}

/**
 * 获取某个网络接口的Mac地址
 * @author chenhongjiao
 * @date 2021/03/26 18:08
 * @since 1.0.0
 * @param
 * @return void
 */
protected String getMacByInetAddress(InetAddress inetAddr){
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值