一、原理说明
首先生成密钥库(加密算法),通过公钥和私钥的匹配情况和授权文件的验证情况来判断是否已授权。需要重新授权的时候使用license可以避免修改源码,改动部署,授权方直接生成一个新的license发送给使用方替换掉原来的license文件即可。
二、使用说明
授权方:
(1)使用keytool工具生成密钥对(公钥和私钥),私钥授权方保存,公钥给使用方。
(2)创建.lic授权文件给使用方。
使用方:
(1)保存公钥
(2)使用时加载.lic授权文件,验证。
三、使用keytool生成密钥对
略,参考前面的文章《使用jdk自带的keytool工具私公钥文件》
四、代码如下
1、导入truelicense相关API包
maven库:
<dependency>
<groupId>de.schlichtherle.truelicense</groupId>
<artifactId>truelicense-core</artifactId>
<version>1.33</version>
</dependency>
2、生成证书
(1)添加一个LicenseManagerHolder类,管理LicenseManager。
代码如下:
import de.schlichtherle.license.LicenseManager;
import de.schlichtherle.license.LicenseParam;
/**
* Desc: license管理类
* User: 叶国栋194
* Date: 2018-03-02 上午10:19
*/
public class LicenseManagerHolder {
private static LicenseManager licenseManager;
public static synchronized LicenseManager getLicenseManager(LicenseParam licenseParam) {
if(null == licenseManager) {
try {
licenseManager = new LicenseManager(licenseParam);
} catch (Exception e) {
e.printStackTrace();
}
}
return licenseManager;
}
}
(2)创建一个createParams.properties配置文件管理生成证书的配置项
#私钥库的别名
privateAlias=privatekey
#该密码是生成密钥对的密码,需要妥善保管,不能让使用者知道
keyPwd=yunshi025
#该密码是在使用keytool生成密钥对时设置的密钥库的访问密码
storePwd=yunshi025
subject=license
#生成的license文件地址,这里是系统路径地址
licPath=/Users/mac/license/license.lic
#私钥库文件的地址,这里是classpath的地址
priPath=/license/privateKey.store
#发布时间
issuedTime=2018-03-01
#从2018-xx-xx开始
notBefore=2018-03-06
#截止到2018-xx-xx为止的前一天
notAfter=2018-06-07
consumerType=user
consumerAmount=1
info=xxx
(3)创建一个生成管理类CreateLicense,在类中定义配置参数
private static String privateAlias = "";
private static String keyPwd = "";
private static String storePwd = "";
private static String subject = "";
private static String licPath = "";
private static String priPath = "";
private static String issuedTime = "";
private static String notBefore = "";
private static String notAfter = "";
private static String consumerType = "";
private static int consumerAmount = 0;
private static String info = "";
//X500Principal对象里的属性值是在创建密钥库时填写的信息,比如姓名、组织名、国家等
private static final X500Principal DEFAULTHOLDERANDISSUER =
new X500Principal(“CN=ye、OU=yunshi、O=yunshi、C=cn");
(4)设置配置参数的函数
public void setParam(String propertiesPath) {
Properties properties = new Properties();
InputStream inputStream = CreateLicense.class.getClassLoader().getResourceAsStream(propertiesPath);
try {
properties.load(inputStream);
}catch (IOException e) {
e.printStackTrace();
}
privateAlias = properties.getProperty("privateAlias");
keyPwd = properties.getProperty("keyPwd");
storePwd = properties.getProperty("storePwd");
subject = properties.getProperty("subject");
licPath = properties.getProperty("licPath");
priPath = properties.getProperty("priPath");
issuedTime = properties.getProperty("issuedTime");
notBefore = properties.getProperty("notBefore");
notAfter = properties.getProperty("notAfter");
consumerType = properties.getProperty("consumerType");
try {
consumerAmount = Integer.valueOf(properties.getProperty("consumerAmount"));
} catch (NumberFormatException e) {
e.printStackTrace();
}
info = properties.getProperty("info");
}
(5)初始化LicenseParams参数的函数
/*
返回生成证书时需要的参数
*/
private static LicenseParam initLicenseParams() {
Preferences preferences = Preferences.userNodeForPackage(CreateLicense.class);
// 设置对证书内容加密的对称密码
CipherParam cipherParam = new DefaultCipherParam(storePwd);
/*
参数1和2从哪个Class.getResource()获得密钥库。
参数3是密钥库的别名。
参数4是密钥库存储密码。
参数5密钥库密码。
*/
KeyStoreParam privateStoreParam = new DefaultKeyStoreParam(
CreateLicense.class,
priPath,
privateAlias,
storePwd,
keyPwd
);
LicenseParam licenseParam = new DefaultLicenseParam(
subject,
preferences,
privateStoreParam,
cipherParam
);
return licenseParam;
}
(6)获取LicenseContent证书内容
/*
从外部表单拿到证书的内容
*/
public final static LicenseContent createLicenseContent() {
DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
LicenseContent content = new LicenseContent();
content.setSubject(subject);
content.setHolder(DEFAULTHOLDERANDISSUER);
content.setIssuer(DEFAULTHOLDERANDISSUER);
try {
content.setIssued(format.parse(issuedTime));
content.setNotBefore(format.parse(notBefore));
content.setNotAfter(format.parse(notAfter));
} catch (ParseException e) {
e.printStackTrace();
}
content.setConsumerType(consumerType);
content.setConsumerAmount(consumerAmount);
content.setInfo(info);
// 扩展,暂时没用
content.setExtra(new Object());
return content;
}
(7)生成证书的函数
public boolean create() {
try {
LicenseManager licenseManager = LicenseManagerHolder.getLicenseManager(initLicenseParams());
File file = new File(licPath);
if(!file.exists()) {
file.createNewFile();
}
licenseManager.store(createLicenseContent(), new File(licPath));
} catch (Exception e) {
e.printStackTrace();
System.out.println("生成失败");
return false;
}
System.out.println("生成成功");
return true;
}
(8)调用样例
public static void main(String[] args) {
CreateLicense createLicense = new CreateLicense();
createLicense.setParam("license/createParams.properties");
createLicense.create();
}
3、验证证书
(1)验证证书代码也需要使用LicenseManagerHolder类来创建LicenseManager
(2)创建一个verifyParams.properties配置文件管理验证证书的配置项
#生成的license文件地址,这里是系统路径地址
licPath=/Users/mac/license/license.lic
#公钥库文件的地址,这里是classpath的地址
pubPath=/license/publicCerts.store
(3)创建一个验证管理类VerifyLicense,在类中定义配置参数
//公钥库的别名
private static String publicAlias = "publiccert";
//密钥库密码
private static String storePwd = "yunshi025";
private static String subject = "license";
private static String licPath = "";
private static String pubPath = "";
(4)设置配置参数的函数
public void setParam(String propertiesPath) {
Properties properties = new Properties();
InputStream inputStream = CreateLicense.class.getClassLoader().getResourceAsStream(propertiesPath);
try {
properties.load(inputStream);
}catch (IOException e) {
e.printStackTrace();
}
//publicAlias = properties.getProperty("publicAlias");
//storePwd = properties.getProperty("storePwd");
//subject = properties.getProperty("subject");
licPath = properties.getProperty("licPath");
pubPath = properties.getProperty("pubPath");
}
(5)初始化LicenseParams参数的函数
private static LicenseParam initLicenseParams() {
Preferences preference = Preferences.userNodeForPackage(VerifyLicense.class);
CipherParam cipherParam = new DefaultCipherParam(storePwd);
KeyStoreParam privateStoreParam = new DefaultKeyStoreParam(
VerifyLicense.class, pubPath, publicAlias, storePwd, null);
LicenseParam licenseParams = new DefaultLicenseParam(subject,
preference, privateStoreParam, cipherParam);
return licenseParams;
}
(6)获取LicenseContent证书内容
public LicenseContent getLicenseContent() {
LicenseContent licenseContent = null;
LicenseManager licenseManager = LicenseManagerHolder
.getLicenseManager(initLicenseParams());
try {
PrivacyGuard privacyGuard = new PrivacyGuard(licenseManager.getLicenseParam().getCipherParam());
GenericCertificate certificate = privacyGuard.key2cert(loadLicenseKey(new File(licPath)));
licenseContent = (LicenseContent)PersistenceService.load(certificate.getEncoded());
} catch (Exception e) {
//e.printStackTrace();
}
return licenseContent;
}
(7)验证函数
public boolean verify() {
LicenseManager licenseManager = LicenseManagerHolder.getLicenseManager(initLicenseParams());
boolean isVerify = false;
// 安装证书
try {
licenseManager.install(new File(licPath));
System.out.println("客户端安装证书成功");
} catch (Exception e) {
//e.printStackTrace();
System.out.println("许可证已过期");
return false;
}
// 验证证书
try {
LicenseContent licenseContent = licenseManager.verify();
System.out.println(licenseContent);
} catch (Exception e) {
//e.printStackTrace();
System.out.println("许可证已过期");
}
System.out.println("客户端验证证书成功");
return isVerify;
}
(8)调用样例
public static void main(String[] args) {
VerifyLicense verifyLicense = new VerifyLicense();
verifyLicense.setParam("license/verifyParams.properties");
verifyLicense.verify();
}