1.license
通過license控制項目證書驗證
我才用的TrueLicense實現(xiàn)lic
首先介紹下 license 授權機制的原理:
生成密鑰對檩互,包含私鑰和公鑰钝吮。
授權者保留私鑰吵取,使用私鑰對授權信息諸如使用截止日期膨蛮,mac 地址等內容生成 license 簽名證書到推。
公鑰給使用者掖看,放在代碼中使用演训,用于驗證 license 簽名證書是否符合使用條件
2.生成公私鑰
1.生成私鑰
keytool -genkey -alias privatekey -keystore privateKeys.store -keysize 1024 -validity 3650
//-validity 3650 表示有效期為10年
// 我這邊設值密碼為123456a, 密令執(zhí)行成功會產生文件privateKeys.store
2.生成certfile.cer(證書)
keytool -export -alias privatekey -file certfile.cer -keystore privateKeys.store
3.生成 publicCerts.store
keytool -import -alias publiccert -file certfile.cer -keystore publicCerts.store
3.生成licence.lic
api "de.schlichtherle.truelicense:truelicense-core:1.33"
licenseCreator
/**
* License生成類 -- 用于license生成
*/
public class LicenseCreator {
private final static X500Principal DEFAULT_HOLDER_AND_ISSUER = new X500Principal("CN=a, OU=a, O=a, L=a, ST=a, C=a");
private static Logger logger = LogManager.getLogger(LicenseCreator.class);
private License license;
public LicenseCreator(License license) {
this.license = license;
}
/**
* 生成License證書
*/
public boolean generateLicense() {
try {
LicenseManager licenseManager = new CustomLicenseManager(initLicenseParam());
LicenseContent licenseContent = initLicenseContent();
licenseManager.store(licenseContent, new File(license.getLicensePath()));
return true;
} catch (Exception e) {
logger.error(MessageFormat.format("證書生成失斝聘怼:{0}", license), e);
return false;
}
}
/**
* 初始化證書生成參數(shù)
*/
private LicenseParam initLicenseParam() {
Preferences preferences = Preferences.userNodeForPackage(LicenseCreator.class);
//設置對證書內容加密的秘鑰
CipherParam cipherParam = new DefaultCipherParam(license.getStorePass());
KeyStoreParam privateStoreParam = new CustomKeyStoreParam(LicenseCreator.class
, license.getPrivateKeysStorePath()
, license.getPrivateAlias()
, license.getStorePass()
, license.getKeyPass());
return new DefaultLicenseParam(license.getSubject()
, preferences
, privateStoreParam
, cipherParam);
}
/**
* 設置證書生成正文信息
*/
private LicenseContent initLicenseContent() {
LicenseContent licenseContent = new LicenseContent();
licenseContent.setHolder(DEFAULT_HOLDER_AND_ISSUER);
licenseContent.setIssuer(DEFAULT_HOLDER_AND_ISSUER);
licenseContent.setSubject(license.getSubject());
licenseContent.setIssued(license.getIssuedTime());
licenseContent.setNotBefore(license.getIssuedTime());
licenseContent.setNotAfter(license.getExpiryTime());
licenseContent.setConsumerType(license.getConsumerType());
licenseContent.setConsumerAmount(license.getConsumerAmount());
licenseContent.setInfo(license.getDescription());
//擴展校驗,這里可以自定義一些額外的校驗信息(也可以用json字符串保存)
if (license.getLicenseExtraModel() != null) {
licenseContent.setExtra(license.getLicenseExtraModel());
}
return licenseContent;
}
}
License信息
@Data
public class License 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;
/**
* 證書生效時間
*/
private Date issuedTime = new Date();
/**
* 證書失效時間
*/
private Date expiryTime;
/**
* 用戶類型
*/
private String consumerType = "user";
/**
* 用戶數(shù)量
*/
private Integer consumerAmount = 1;
/**
* 描述信息
*/
private String description = "";
/**
* 額外的服務器硬件校驗信息
*/
private LicenseExtraModel licenseExtraModel;
}
LicenseExtraModel其它自定義的參數(shù)
/**
* 自定義需要校驗的License參數(shù)隙弛,可以增加一些額外需要校驗的參數(shù),比如項目信息狞山,ip地址信息等等全闷,待完善
*/
@Data
public class LicenseExtraModel {
// 這里可以添加一些往外的自定義信息,比如我們可以增加項目驗證萍启,客戶電腦sn碼的驗證等等
private Boolean flag;
}
生成license
public static void main(String[] args) {
// 生成license需要的一些參數(shù)
License param = new License();
// 證書授權主體
param.setSubject("summit");
// 私鑰別名
param.setPrivateAlias("privateKey");
// 私鑰密碼(需要妥善保管总珠,不能讓使用者知道)
param.setKeyPass("123456a");
// 訪問私鑰庫的密碼
param.setStorePass("123456a");
// 證書存儲地址
param.setLicensePath("C:\\java-kaifa\\tongyu-workspace\\me\\springboot-jar\\my-stater\\src\\main\\resources\\license.lic");
// 私鑰庫所在地址
param.setPrivateKeysStorePath("C:\\java-kaifa\\tongyu-workspace\\me\\springboot-jar\\my-stater\\privateKeys.store");
// 證書生效時間
Calendar issueCalendar = Calendar.getInstance();
param.setIssuedTime(issueCalendar.getTime());
// 證書失效時間
Calendar expiryCalendar = Calendar.getInstance();
// 設置當前時間
expiryCalendar.setTime(new Date());
// 往后延長一年 = 授權一年時間
expiryCalendar.add(Calendar.YEAR, 1);
param.setExpiryTime(expiryCalendar.getTime());
// 用戶類型
param.setConsumerType("user");
// 用戶數(shù)量
param.setConsumerAmount(1);
// 描述
param.setDescription("測試");
LicenseExtraModel model = new LicenseExtraModel();
model.setFlag(true);
param.setLicenseExtraModel(model);
LicenseCreator licenseCreator = new LicenseCreator(param);
// 生成license
licenseCreator.generateLicense();
}
4.驗證license
public class LicenseVerify {
private static Logger logger = LogManager.getLogger(LicenseVerify.class);
/**
* 證書subject
*/
private String subject;
/**
* 公鑰別稱
*/
private String publicAlias;
/**
* 訪問公鑰庫的密碼
*/
private String storePass;
/**
* 證書生成路徑
*/
private String licensePath;
/**
* 密鑰庫存儲路徑
*/
private String publicKeysStorePath;
/**
* LicenseManager
*/
private LicenseManager licenseManager;
/**
* 額外參數(shù)
*/
private LicenseExtraModel licenseExtraParam;
public LicenseExtraModel getLicenseExtraParam() {
return licenseExtraParam;
}
/**
* 標識證書是否安裝成功
*/
private boolean installSuccess;
public LicenseVerify(String subject, String publicAlias, String storePass, String licensePath, String publicKeysStorePath) {
this.subject = subject;
this.publicAlias = publicAlias;
this.storePass = storePass;
this.licensePath = licensePath;
this.publicKeysStorePath = publicKeysStorePath;
}
/**
* 安裝License證書,讀取證書相關的信息, 在bean加入容器的時候自動調用
*/
public void installLicense() {
try {
Preferences preferences = Preferences.userNodeForPackage(LicenseVerify.class);
CipherParam cipherParam = new DefaultCipherParam(storePass);
KeyStoreParam publicStoreParam = new CustomKeyStoreParam(LicenseVerify.class,
publicKeysStorePath,
publicAlias,
storePass,
null);
LicenseParam licenseParam = new DefaultLicenseParam(subject, preferences, publicStoreParam, cipherParam);
licenseManager = new CustomLicenseManager(licenseParam);
licenseManager.uninstall();
LicenseContent licenseContent = licenseManager.install(new File(licensePath));
licenseExtraParam = (LicenseExtraModel) licenseContent.getExtra();
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
installSuccess = true;
logger.info("------------------------------- 證書安裝成功 -------------------------------");
logger.info(MessageFormat.format("證書有效期:{0} - {1}", format.format(licenseContent.getNotBefore()), format.format(licenseContent.getNotAfter())));
} catch (Exception e) {
installSuccess = false;
logger.error("------------------------------- 證書安裝失敗 -------------------------------");
logger.error(e);
}
}
/**
* 卸載證書勘纯,在bean從容器移除的時候自動調用
*/
public void unInstallLicense() {
if (installSuccess) {
try {
licenseManager.uninstall();
} catch (Exception e) {
// ignore
}
}
}
/**
* 校驗License證書
*/
public boolean verify() {
try {
LicenseContent licenseContent = licenseManager.verify();
return true;
} catch (Exception e) {
return false;
}
}
}
測試
public static void main(String[] args) {
LicenseVerify licenseVerify = new LicenseVerify("summit", "publiccert", "123456b",
"C:\\java-kaifa\\tongyu-workspace\\me\\springboot-jar\\my-stater\\src\\main\\resources\\license.lic",
"C:\\java-kaifa\\tongyu-workspace\\me\\springboot-jar\\my-stater\\src\\main\\resources\\publicCerts.store"
);
licenseVerify.installLicense();
licenseVerify.verify();
}
// 打印結果
//> Task :my-stater:VerifyMain.main()
//16:21:08.553 [main] INFO cn.summit.licence.comm.LicenseVerify - ------------------------------- 證書安裝成功 -----------------
//16:21:08.559 [main] INFO cn.summit.licence.comm.LicenseVerify - 證書有效期:2022-07-28 16:20:28 - 2023-07-28 16:20:28
5.集合project
代碼見代碼地址
@Configuration
public class LicenseConfig {
@Bean(initMethod = "installLicense", destroyMethod = "unInstallLicense")
public LicenseVerify licenseVerify() {
return new LicenseVerify(subject, publicAlias, storePass, licensePath, publicKeysStorePath);
}
/**
* 證書subject
*/
@Value("${license.subject:summit}")
private String subject;
/**
* 公鑰別稱
*/
@Value("${license.publicAlias:publiccert}")
private String publicAlias;
/**
* 訪問公鑰庫的密碼
*/
@Value("${license.storePass:123456b}")
private String storePass;
/**
* 證書生成路徑
*/
@Value("${license.licensePath:C:\\java-kaifa\\tongyu-workspace\\me\\springboot-jar\\my-stater\\src\\main\\resources\\license.lic}")
private String licensePath;
/**
* 密鑰庫存儲路徑
*/
@Value("${license.publicKeysStorePath:classpath:publicCerts.store}")
private String publicKeysStorePath;
}
實際使用中可以將項目中一些參數(shù)放入LicenseExtraModel對象局服,在項目啟動的時候控制一些業(yè)務上權限