truelicense相关原理可以参考第一篇:http://blog.csdn.net/luckymelina/article/details/22870665
本文参考第二篇:http://blog.csdn.net/jingshuaizh/article/details/44461289
第一篇能够让刚接触truelicense的童鞋很成功的上手并测试成功,由于项目需要mac验证,所以参考第二篇,介于发现有些网友反应有错误,本人也遇到错误,后贴上成功运行的工程仅供参考。
添加mac验证功能需要修改truelicense源码,可以参考第二篇的git地址下载源码:https://github.com/jingshauizh/JavaSpringSurmmary/tree/master/java-license-jar
添加mac验证的原理是添加mac信息到license context 并生成license文件,然后在验证程序中加入mac验证算法,验证时读取license文件中的mac信息,然后验证~
接下来是本例制作license的具体步骤:
使用keytool生成密钥对
以下命令在dos命令行执行,注意当前执行目录,最后生成的密钥对即在该目录下:
1、首先要用KeyTool工具来生成私匙库:(-alias别名 –validity 3650表示10年有效)
keytool -genkey -alias privatekey -keystore privateKeys.store -validity 3650
2、然后把私匙库内的公匙导出到一个文件当中:
keytool -export -alias privatekey -file certfile.cer -keystore privateKeys.store
3、然后再把这个证书文件导入到公匙库:
keytool -import -alias publiccert -file certfile.cer -keystore publicCerts.store
最后生成文件privateKeys.store、publicCerts.store拷贝出来备用。
以上是在windows机器上的预备动作。
接下来开始修改程序:
1、修改生成licence代码。
生成license程序中 createparam.properties:
##########common parameters###########
#alias
PRIVATEALIAS=privatekey
#key(该密码生成密钥对的密码,需要妥善保管,不能让使用者知道)
KEYPWD=bigdata123456
#STOREPWD(该密码是在使用keytool生成密钥对时设置的密钥库的访问密码)
STOREPWD=abc123456
#SUBJECT
SUBJECT=bigdata
#licPath
licPath=bigdata.lic
#priPath
priPath=privateKeys.store
##########license content###########
#issuedTime
issuedTime=2017-05-01
#notBeforeTime
notBefore=2017-05-01
#notAfterTime
notAfter=2017-06-10
#consumerType
consumerType=user
#ConsumerAmount
consumerAmount=1
#info
info=this is a license
#mac
mac=D8-CB-8A-04-51-10
然后通过content.setExtra()方法添加mac信息到license content,这是主要生成license的代码CreateLicense.java:
//license content
issuedTime = prop.getProperty("issuedTime");
notBefore = prop.getProperty("notBefore");
notAfter = prop.getProperty("notAfter");
consumerType = prop.getProperty("consumerType");
consumerAmount = Integer.valueOf(prop.getProperty("consumerAmount"));
info = prop.getProperty("info");
mac = prop.getProperty("mac");
ip = prop.getProperty("ip");
content.setConsumerType(consumerType);
content.setConsumerAmount(consumerAmount);
content.setInfo(info);
// 扩展
//content.setExtra(new Object());
content.setExtra(mac);
这里的setExtra可以传入一个object,如果除了mac地址还需要其他验证,可以传入一个model类,这里只传入一个mac String字符串。
以上修改即可完成licence文件生成。
2、修改验证licence代码
验证时使用到的Properties文件如下:
##########common parameters###########
#alias
PUBLICALIAS=publiccert
#STOREPWD
STOREPWD=abc123456
#SUBJECT
SUBJECT=bigdata
#licPath
licPath=D:\\tmp\\bigdata.lic
#pubPath
pubPath=D:\\tmp\\publicCerts.store
接下来修改LicenseManager.java源码中的validate方法,主要是从licence中读取mac值并使用算法进行验证。
String macAddress = paramLicenseContent.getExtra().toString();
try {
if (!ListNets.validateMacAddress(macAddress)) {
throw new LicenseContentException(EXC_LICENSE_HAS_EXPIRED);
}
} catch (SocketException e) {
// TODO Auto-generated catch block
throw new LicenseContentException(EXC_LICENSE_HAS_EXPIRED);
}
ListNets类如下:
package zlicense.de.schlichtherle.utils;
import java.net.*;
import java.util.*;
import static java.lang.System.out;
public class ListNets {
public static void main(String args[]) throws SocketException {
String ip = "192.168.3.212";
String mac = "D8-CB-8A-04-51-10";
boolean flag = validatoIpAndMacAddress(ip, mac);
boolean macflag = validateMacAddress( mac);
out.printf("validatoMacAddress flag=%s\n", macflag);
out.printf("validatoIpAndMacAddress flag=%s\n", flag);
}
static void displayInterfaceInformation(NetworkInterface netint)
throws SocketException {
out.printf("Display name: %s\n", netint.getDisplayName());
out.printf("Name: %s\n", netint.getName());
byte[] mac = netint.getHardwareAddress();
if (mac != null) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < mac.length; i++) {
sb.append(String.format("%02X%s", mac[i],
(i < mac.length - 1) ? "-" : ""));
}
System.out.println("mac=" + sb.toString());
}
Enumeration<InetAddress> inetAddresses = netint.getInetAddresses();
for (InetAddress inetAddress : Collections.list(inetAddresses)) {
out.printf("InetAddress: %s\n", inetAddress);
System.out
.println("InetAddress ip=" + inetAddress.getHostAddress());
}
out.printf("\n");
}
public static boolean validateMacAddress(String macAddress)
throws SocketException {
boolean returnFlag = false;
Enumeration<NetworkInterface> nets = NetworkInterface
.getNetworkInterfaces();
for (NetworkInterface netint : Collections.list(nets)) {
byte[] mac = netint.getHardwareAddress();
StringBuilder sb = new StringBuilder();
if (mac != null) {
for (int i = 0; i < mac.length; i++) {
sb.append(String.format("%02X%s", mac[i],
(i < mac.length - 1) ? "-" : ""));
}
System.out.println("mac=" + sb.toString());
}
if (sb.toString().equals(macAddress)) {
returnFlag = true;
}
}
return returnFlag;
}
public static boolean validatoIpAndMacAddress(String ipAddress,
String macAddress) throws SocketException {
boolean returnFlag = false;
Enumeration<NetworkInterface> nets = NetworkInterface
.getNetworkInterfaces();
for (NetworkInterface netint : Collections.list(nets)) {
byte[] mac = netint.getHardwareAddress();
StringBuilder sb = new StringBuilder();
if (mac != null) {
for (int i = 0; i < mac.length; i++) {
sb.append(String.format("%02X%s", mac[i],
(i < mac.length - 1) ? "-" : ""));
}
System.out.println("mac=" + sb.toString());
}
if (sb.toString().equals(macAddress)) {
Enumeration<InetAddress> inetAddresses = netint
.getInetAddresses();
String ip = "";
for (InetAddress inetAddress : Collections.list(inetAddresses)) {
ip = inetAddress.getHostAddress();
System.out.println("InetAddress ip="
+ inetAddress.getHostAddress());
if (ipAddress.toString().equals(ip)) {
returnFlag = true;
}
}
}
}
return returnFlag;
}
}
这里只用到了其中一个验证mac的算法,如果有其他需求,可以在这里添加验证。
最后是生成和验证程序的入口(不需要修改,只执行):
public class licenseCreateTest {
public static void main(String[] args){
CreateLicense cLicense = new CreateLicense();
//获取参数
cLicense.setParam("./param.properties");
//生成证书
cLicense.create();
}
}
public class licenseVerifyTest {
public static void main(String[] args){
VerifyLicense vLicense = new VerifyLicense();
//获取参数
vLicense.setParam("D:\\tmp\\param.properties");
//生成证书
vLicense.verify();
}
}
到这里代码修改完毕。有一个需要注意的问题:生成和验证licence的工程包名需要一致,否则会报强转错误。
以上逻辑搞清楚后,完全可以自己测试了。这里放上我的测试工程,仅供参考:
http://download.csdn.net/download/qq_27499099/9838931