1. 程式人生 > >使用truelicense實現用於JAVA工程license機制(包括license生成和驗證)

使用truelicense實現用於JAVA工程license機制(包括license生成和驗證)

參數 cat this false sem inf import 存儲密碼 dos命令

開發的軟件產品在交付使用的時候,往往會授權一段時間的試用期,這個時候license就派上用場了。不同於在代碼中直接加上時間約束,需要重新授權的時候使用license可以避免修改源碼,改動部署,授權方直接生成一個新的license發送給使用方替換掉原來的license文件即可。下面將講述使用truelicense來實現license的生成和使用。Truelicense是一個開源的證書管理引擎,詳細介紹見 https://truelicense.java.net/ [此地址已不可用(蘇醒若蘅註)]

一、首先介紹下license授權機制的原理:

1、 生成密鑰對,方法有很多。

2、 授權者保留私鑰,使用私鑰對包含授權信息(如使用截止日期,MAC地址等)的license進行數字簽名。

3、 公鑰給使用者(放在驗證的代碼中使用),用於驗證license是否符合使用條件。

接下來是本例制作license的具體步驟:

二、第一步:使用keytool生成密鑰對

以下命令在dos命令行執行,註意當前執行目錄,最後生成的密鑰對即在該目錄下:

1、首先要用KeyTool工具來生成私匙庫:(-alias別名 –validity 3650表示10年有效)

keytool -genkey -alias privatekey -keystoreprivateKeys.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拷貝出來備用。

三、第二步:生成證書(該部分代碼由授權者獨立保管執行)

1、 首先LicenseManagerHolder.java類:

package cn.melina.license;

import de.schlichtherle.license.LicenseManager;
import de.schlichtherle.license.LicenseParam; /** * LicenseManager容器類 * * @author melina */ public class LicenseManagerHolder { private static LicenseManager licenseManager; public static synchronized LicenseManager getLicenseManager(LicenseParam licenseParams) { if (licenseManager == null) { licenseManager = new LicenseManager(licenseParams); } return licenseManager; } }

2、 然後是主要生成license的代碼CreateLicense.java:

  

package cn.melina.license;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Properties;
import java.util.prefs.Preferences;
import javax.security.auth.x500.X500Principal;
import de.schlichtherle.license.CipherParam;
import de.schlichtherle.license.DefaultCipherParam;
import de.schlichtherle.license.DefaultKeyStoreParam;
import de.schlichtherle.license.DefaultLicenseParam;
import de.schlichtherle.license.KeyStoreParam;
import de.schlichtherle.license.LicenseContent;
import de.schlichtherle.license.LicenseParam;
import de.schlichtherle.license.LicenseManager;

/**
 * CreateLicense
 * @author melina
 */
public class CreateLicense {
    //common param
    private static String PRIVATEALIAS = "";
    private static String KEYPWD = "";
    private static String STOREPWD = "";
    private static String SUBJECT = "";
    private static String licPath = "";
    private static String priPath = "";
    //license content
    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 = "";
    // 為了方便直接用的API裏的例子
    // X500Princal是一個證書文件的固有格式,詳見API
    private final static X500Principal DEFAULTHOLDERANDISSUER = new X500Principal(
            "CN=Duke、OU=JavaSoft、O=Sun Microsystems、C=US");
    
    public void setParam(String propertiesPath) {
        // 獲取參數
        Properties prop = new Properties();
        InputStream in = getClass().getResourceAsStream(propertiesPath);
        try {
            prop.load(in);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        PRIVATEALIAS = prop.getProperty("PRIVATEALIAS");
        KEYPWD = prop.getProperty("KEYPWD");
        STOREPWD = prop.getProperty("STOREPWD");
        SUBJECT = prop.getProperty("SUBJECT");
        KEYPWD = prop.getProperty("KEYPWD");
        licPath = prop.getProperty("licPath");
        priPath = prop.getProperty("priPath");
        //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");
        
    }

    public boolean create() {        
        try {
            /************** 證書發布者端執行 ******************/
            LicenseManager licenseManager = LicenseManagerHolder
                    .getLicenseManager(initLicenseParams0());
            licenseManager.store((createLicenseContent()), new File(licPath));    
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("客戶端證書生成失敗!");
            return false;
        }
        System.out.println("服務器端生成證書成功!");
        return true;
    }

    // 返回生成證書時需要的參數
    private static LicenseParam initLicenseParams0() {
        Preferences preference = 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 licenseParams = new DefaultLicenseParam(SUBJECT,
                preference, privateStoreParam, cipherParam);
        return licenseParams;
    }

    // 從外部表單拿到證書的內容
        public final static LicenseContent createLicenseContent() {
            DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            LicenseContent content = null;
            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) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            content.setConsumerType(consumerType);
            content.setConsumerAmount(consumerAmount);
            content.setInfo(info);
            // 擴展
            content.setExtra(new Object());
            return content;
        }
}

3、 測試程序licenseCreateTest.java:

  

package cn.melina.license;

import cn.melina.license.CreateLicense;

public class licenseCreateTest {
    public static void main(String[] args){
        CreateLicense cLicense = new CreateLicense();
        //獲取參數
        cLicense.setParam("./param.properties");
        //生成證書
        cLicense.create();
    }
}

4、 生成時使用到的param.properties文件如下:

##########common parameters###########
#alias
PRIVATEALIAS=privatekey
#key(important!)
KEYPWD=bigdata123456
#STOREPWD
STOREPWD=abc123456
#SUBJECT
SUBJECT=bigdata
#licPath
licPath=bigdata.lic
#priPath
priPath=privateKeys.store
##########license content###########
#issuedTime
issuedTime=2014-04-01
#notBeforeTime
notBefore=2014-04-01
#notAfterTime
notAfter=2014-05-01
#consumerType
consumerType=user
#ConsumerAmount
consumerAmount=1
#info
info=this is a license

根據properties文件可以看出,這裏只簡單設置了使用時間的限制,當然可以自定義添加更多限制。該文件中表示授權者擁有私鑰,並且知道生成密鑰對的密碼。並且設置license的內容。

四、第三步:驗證證書(使用證書)(該部分代碼結合需要授權的程序使用)

1、 首先LicenseManagerHolder.java類,同上。

2、 然後是主要驗證license的代碼VerifyLicense.java:

  

package cn.melina.license;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.prefs.Preferences;

import de.schlichtherle.license.CipherParam;
import de.schlichtherle.license.DefaultCipherParam;
import de.schlichtherle.license.DefaultKeyStoreParam;
import de.schlichtherle.license.DefaultLicenseParam;
import de.schlichtherle.license.KeyStoreParam;
import de.schlichtherle.license.LicenseParam;
import de.schlichtherle.license.LicenseManager;

/**
 * VerifyLicense
 * @author melina
 */
public class VerifyLicense {
    //common param
    private static String PUBLICALIAS = "";
    private static String STOREPWD = "";
    private static String SUBJECT = "";
    private static String licPath = "";
    private static String pubPath = "";
    
    public void setParam(String propertiesPath) {
        // 獲取參數
        Properties prop = new Properties();
        InputStream in = getClass().getResourceAsStream(propertiesPath);
        try {
            prop.load(in);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        PUBLICALIAS = prop.getProperty("PUBLICALIAS");
        STOREPWD = prop.getProperty("STOREPWD");
        SUBJECT = prop.getProperty("SUBJECT");
        licPath = prop.getProperty("licPath");
        pubPath = prop.getProperty("pubPath");
    }

    public boolean verify() {        
        /************** 證書使用者端執行 ******************/

        LicenseManager licenseManager = LicenseManagerHolder
                .getLicenseManager(initLicenseParams());
        // 安裝證書
        try {
            licenseManager.install(new File(licPath));
            System.out.println("客戶端安裝證書成功!");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("客戶端證書安裝失敗!");
            return false;
        }
        // 驗證證書
        try {
            licenseManager.verify();
            System.out.println("客戶端驗證證書成功!");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("客戶端證書驗證失效!");
            return false;
        }
        return true;
    }

    // 返回驗證證書需要的參數
    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;
    }
}

3、 測試程序licenseVerifyTest.java:

  

package cn.melina.license;

public class licenseVerifyTest {
    public static void main(String[] args){
        VerifyLicense vLicense = new VerifyLicense();
        //獲取參數
        vLicense.setParam("./param.properties");
        //生成證書
        vLicense.verify();
    }
}

4、 驗證時使用到的Properties文件如下:

##########common parameters###########
#alias
PUBLICALIAS=publiccert
#STOREPWD
STOREPWD=abc123456
#SUBJECT
SUBJECT=bigdata
#licPath
licPath=bigdata.lic
#pubPath
pubPath=publicCerts.store

根據該驗證的properties可以看出,使用者只擁有公鑰,沒有私鑰,並且也只知道訪問密鑰庫的密碼,而不能知道生成密鑰對的密碼。

五、說明:

註意實際操作中,公鑰、私鑰、證書等文件的存放路徑。

以上代碼需要用到truelicense的一些包,可以自行網上搜,也可以下載我的完整工程,裏面附帶了所需的jar包。

以上兩個完整工程提供下載:http://download.csdn.net/detail/luckymelina/7141131

GOOD LUCK!小夥伴們加油!歡迎與我交流。

轉載自:https://blog.csdn.net/luckymelina/article/details/22870665

使用truelicense實現用於JAVA工程license機制(包括license生成和驗證)