基于 TrueLicense 实现 web 应用的 License 验证

近期开发的 web 应用交付海外客户试用时,领导要求需要限制客户的试用期限,于是考虑使用 license 进行授权。查阅相关资料,了解到一个开源的证书管理引擎 ——TrueLicense,通过 TrueLicense 可以实现授权验证功能,用于 license 的生成和有效性的验证。

# 一、License 授权和验证的原理 > - 首先,需要生成密钥对,生成方法有很多,本次项目使用的是 JDK 提供的 KeyTool 工具; > - 在服务端,也就是授权者通过私钥(授权者保留,不能泄露)对包含授权信息(如起始日期、截止日期,服务器硬件的 MAC 地址等)的 license 进行数字签名; > - 在客户端,也就是软件的使用方,通过公钥(一般放在验证的代码中使用)验证 license 是否符合使用条件。

二、实现步骤

1. 生成密钥对

1.1. 生成私钥库

安装 jdk,并配置环境变量,然后使用 KeyTool 工具生成密钥对,命令如下:

1
keytool -genkeypair -keysize 1024 -validity 3650 -alias SYSHLANG -keystore privateKeys.keystore -storepass 12345678A -keypass 12345678A -dname "CN=syshlang, OU=syshlang, O=syshlang, L=GZ, ST=GD, C=CN"

参数说明:

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

genkeypair

1.2. 导出公钥

这一步主要是把私钥库内的公匙导出到一个文件中,命令如下:

1
keytool -exportcert -alias SYSHLANG -keystore privateKeys.keystore -storepass 12345678A -file certfile.cer

参数说明:

  • alias 私钥别称
  • keystore 指定私钥库文件的名称 (如果没有带路径,在当前目录查找)
  • storepass 指定私钥库的密码
  • file 导出证书文件名称

exportcert

1.3. 导入证书文件

这一步主要是把上一步中导出的证书文件导入到公钥库中,命令如下:

1
keytool -import -alias SYSHLANG -file certfile.cer -keystore publicCerts.keystore  -storepass 12345678A

参数说明:

  • alias 公钥别称
  • file 证书文件名称
  • keystore 公钥文件名称
  • storepass 指定私钥库的密码

import

是否信任此证书?[否]:” ,那么请输入”Y”;此步骤中如果没有 storepass 会提示输入输入密钥库口令,输入之前设置的即可,如果没有设置口令,则输入信任证书默认密钥 “changeit”。

如果顺利通过以上的步骤,会在当前目录下生成三个文件:
执行完成生成的三个文件

  • certfile.cer 认证证书,已经没用了,可以删掉
  • privateKeys.keystore 私钥,授权者保留,不能泄露
  • publicCerts.keystore 公钥,给客人使用(一般放在验证的代码中使用)

此时,可以查看 cacerts 中的证书列表

1
2
keytool -list -keystore $JAVA_HOME/jre/lib/security/cacerts  -storepass changeit   //  查看所有
keytool -list -alias SYSHLANG -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit // 查看指定别名

删除 cacerts 中指定名称的证书

1
keytool -delete -alias SYSHLANG -keystore $JAVA_HOME/jre/lib/security/cacerts  -storepass changeit

2. 使用 TrueLicense 实现授权验证

2.1 服务端生成授权证书

TrueLicense 默认只帮我们验证了时间,可以自定义加入一些需要验证的其它信息,例如,服务器硬件的 MAC 地址、CPU 序列号等。然后调用私钥(privateKeys.keystore)生成授权证书文件(license.lic)。

1
2
3
public class LicenseCreateParam implements Serializable {
// 添加自定义验证的信息字段
}

具体代码实现,可以点击服务端代码链接查看。

2.2 客户端验证授权证书

在客户端,继承 LicenseManager 类,重写 verify 方法,校验自定义加入一些需要验证的其它信息。将公钥(publicCerts.keystore)放在项目中,将授权证书文件(license.lic)放到对应的路径即可。

1
2
3
4
5
6
public class ClientLicenseManager extends LicenseManager {
@Override
protected synchronized LicenseContent verify(LicenseNotary licenseNotary) throws LicenseContentException {
// 重写verify方法,校验自定义信息
}
}

具体代码实现,可以点击客户端代码链接查看。