javaEE防盗版-License开发


本文转载自:http://blog.csdn.net/lee272616/article/details/55057311
以下为转载内容:

前言

开发的软件产品在交付使用的时候,往往会授权一段时间的试用期,这个时候license就派上用场了。不同于在代码中直接加上时间约束,需要重新授权的时候使用license可以避免修改源码,改动部署,授权方直接生成一个新的license发送给使用方替换掉原来的license文件即可。下面将讲述使用truelicense来实现license的生成和使用。Truelicense是一个开源的证书管理引擎,详细介绍见https://truelicense.java.net/
license于加密技术一起使用效果更好。
接下来介绍一下license授权机制的原理:
1、生成密钥对,方法有很多。
2、授权者保留私钥,使用私钥对包含授权信息(如使用截止日期,MAC地址等)的license进行数字签名。
3、公钥给使用者(放在验证的代码中使用),用于验证license是否符合使用条件。

使用方式

1. 生成密钥对

以下命令在dos命令行执行,注意当前执行目录,最后生成的密钥对即在该目录下:
1、首先要用KeyTool工具来生成私匙库:(-alias别名 –validity 3650表示10年有效)
keytool -genkey -alias privatekey -keystore privateKeys.store -validity 3650
 
这里口令使用了noryar123
 
这里的口令是:noryar456
这个时候,会在打开命令行的地方创建出一个文件,privateKeys.store


2、然后把私匙库内的证书导出到一个文件当中:
keytool -export -alias privatekey -file certfile.cer -keystore privateKeys.store
 
口令:noryar123


3、然后再把这个证书文件导入到公匙库:
keytool -import -alias publiccert -file certfile.cer -keystore publicCerts.store
 
这里的口令,用了:noryar123


最后生成文件privateKeys.store、publicCerts.store拷贝出来备用。
文件位置在用户目录下
C:\Users\Administrator
从上面我们可以看到,密钥一共有两种:1. 密钥库,这个需要配置到服务器中。2. 密钥,这个需要保护好,是创建私钥的时候用的

2. Maven

[plain]  view plain  copy
  1. <!-- https://mvnrepository.com/artifact/de.schlichtherle.truelicense/truelicense-core -->  
  2. <dependency>  
  3.     <groupId>de.schlichtherle.truelicense</groupId>  
  4.     <artifactId>truelicense-core</artifactId>  
  5.     <version>1.33</version>  
  6. </dependency>  
  7. <!-- https://mvnrepository.com/artifact/de.schlichtherle.truelicense/truelicense-xml -->  
  8. <dependency>  
  9.     <groupId>de.schlichtherle.truelicense</groupId>  
  10.     <artifactId>truelicense-xml</artifactId>  
  11.     <version>1.33</version>  
  12. </dependency>  
  13. <!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->  
  14. <dependency>  
  15.     <groupId>commons-codec</groupId>  
  16.     <artifactId>commons-codec</artifactId>  
  17.     <version>1.10</version>  
  18. </dependency>  
  19. <!-- https://mvnrepository.com/artifact/de.schlichtherle.truelicense/truelicense-swing -->  
  20. <dependency>  
  21.     <groupId>de.schlichtherle.truelicense</groupId>  
  22.     <artifactId>truelicense-swing</artifactId>  
  23.     <version>1.33</version>  
  24. </dependency>  

3. 生成证书 (该部分代码由授权者独立保管执行)

[java]  view plain  copy
  1. package com.noryar.license;  
  2. import de.schlichtherle.license.LicenseManager;  
  3. import de.schlichtherle.license.LicenseParam;  
  4. /** 
  5.  * 单例模式下的证书管理器 
  6.  * @author Leon Lee. 
  7.  */  
  8. public class LicenseManagerHolder  
  9. {  
  10.     private static LicenseManager licenseManager;  
  11.     private LicenseManagerHolder(){}  
  12.     public static synchronized  LicenseManager getLicenseManager(LicenseParam param)  
  13.     {  
  14.         if(licenseManager==null)  
  15.         {  
  16.             licenseManager=new LicenseManager(param);  
  17.         }  
  18.         return licenseManager;  
  19.     }  
  20. }  

[java]  view plain  copy
  1. package com.noryar.license;  
  2.   
  3. import java.io.File;  
  4. import java.io.IOException;  
  5. import java.io.InputStream;  
  6. import java.text.ParseException;  
  7. import java.text.SimpleDateFormat;  
  8. import java.util.Properties;  
  9. import java.util.prefs.Preferences;  
  10.   
  11. import javax.security.auth.x500.X500Principal;  
  12.   
  13. import de.schlichtherle.license.CipherParam;  
  14. import de.schlichtherle.license.DefaultCipherParam;  
  15. import de.schlichtherle.license.DefaultKeyStoreParam;  
  16. import de.schlichtherle.license.DefaultLicenseParam;  
  17. import de.schlichtherle.license.KeyStoreParam;  
  18. import de.schlichtherle.license.LicenseContent;  
  19. import de.schlichtherle.license.LicenseManager;  
  20. import de.schlichtherle.license.LicenseParam;  
  21.   
  22. /** 
  23.  * 生成证书 
  24.  * @author Leon Lee. 
  25.  */  
  26. public class LicenseMake  
  27. {  
  28.     private String licPath;  
  29.     private String issued ;  
  30.     private String notBefore ;  
  31.     private String notAfter ;  
  32.     private String consumerType;  
  33.     private int consumerAmount ;  
  34.     private String info ;  
  35.     /** 
  36.      * 私钥的别名 
  37.      */  
  38.     private String priAlias ;  
  39.     /** 
  40.      * 该密码生成密钥对的密码 
  41.      */  
  42.     private String privateKeyPwd ;  
  43.     /** 
  44.      * 使用keytool生成密钥对时设置的密钥库的访问密码 
  45.      */  
  46.     private String keyStorePwd ;  
  47.     private String subject ;  
  48.     private String priPath ;  
  49.       
  50.     // X500Princal是一个证书文件的固有格式,详见API  
  51.     private final static X500Principal DEFAULTHOLDERANDISSUER = new X500Principal("CN=noryar, OU=noryar, O=noryar, L=china, ST=dalian, C=china");  
  52.       
  53.     public LicenseMake(){}  
  54.     public LicenseMake(String confPath)  
  55.     {  
  56.         initParam(confPath);  
  57.     }  
  58.       
  59.     /** 
  60.      * 读取属性文件 
  61.      * @param propertiesPath 属性文件路径 
  62.      */  
  63.     public void initParam(String confPath)   
  64.     {  
  65.         // 获取参数  
  66.         Properties prop = new Properties();  
  67.         InputStream in = getClass().getResourceAsStream(confPath);  
  68.         try  
  69.         {  
  70.             prop.load(in);  
  71.         }  
  72.         catch (IOException e)  
  73.         {  
  74.             e.printStackTrace();  
  75.         }  
  76.         //common param  
  77.         priAlias = prop.getProperty("private.key.alias");  
  78.         privateKeyPwd = prop.getProperty("private.key.pwd");  
  79.         keyStorePwd= prop.getProperty("key.store.pwd");  
  80.         subject = prop.getProperty("subject");  
  81.         priPath = prop.getProperty("priPath");  
  82.         licPath = prop.getProperty("licPath");  
  83.          // license content  
  84.         issued = prop.getProperty("issuedTime");  
  85.         notBefore = prop.getProperty("notBefore");  
  86.         notAfter = prop.getProperty("notAfter");  
  87.         consumerType = prop.getProperty("consumerType");  
  88.         consumerAmount = Integer.valueOf(prop.getProperty("consumerAmount"));  
  89.         info = prop.getProperty("info");  
  90.     }  
  91.       
  92.     /** 
  93.      * 初始化证书的相关参数 
  94.      * @return 
  95.      */  
  96.     private LicenseParam initLicenseParams()  
  97.     {  
  98.         Class<LicenseMake> clazz=LicenseMake.class;  
  99.         Preferences pre = Preferences.userNodeForPackage(clazz);  
  100.         // 设置对证书内容加密的对称密码  
  101.         CipherParam cipherParam = new DefaultCipherParam(keyStorePwd);  
  102.         // 参数1,2从哪个Class.getResource()获得密钥库;  
  103.         //参数3密钥库的别名;  
  104.         //参数4密钥库存储密码;  
  105.         //参数5密钥库密码  
  106.         KeyStoreParam privateStoreParam = new DefaultKeyStoreParam(clazz, priPath, priAlias, keyStorePwd, privateKeyPwd);  
  107.         // 返回生成证书时需要的参数  
  108.         LicenseParam licenseParam = new DefaultLicenseParam(subject,pre, privateStoreParam, cipherParam);  
  109.         return licenseParam;  
  110.     }  
  111.       
  112.     /** 
  113.      * 通过外部配置文件构建证书的的相关信息 
  114.      * @return 
  115.      * @throws ParseException 
  116.      */  
  117.     public LicenseContent buildLicenseContent() throws ParseException  
  118.     {  
  119.         LicenseContent content=new LicenseContent();  
  120.         SimpleDateFormat formate=new SimpleDateFormat("yyyy-MM-dd");  
  121.         content.setConsumerAmount(consumerAmount);  
  122.         content.setConsumerType(consumerType);  
  123.         content.setHolder(DEFAULTHOLDERANDISSUER);  
  124.         content.setIssuer(DEFAULTHOLDERANDISSUER);  
  125.         content.setIssued(formate.parse(issued));  
  126.         content.setNotBefore(formate.parse(notBefore));  
  127.         content.setNotAfter(formate.parse(notAfter));  
  128.         content.setInfo(info);  
  129.         content.setExtra(new Object());  
  130.         return content;  
  131.     }  
  132.       
  133.       
  134.     /** 
  135.      * 生成证书,在证书发布者端执行 
  136.      * @throws Exception  
  137.      */  
  138.     public void create() throws Exception  
  139.     {  
  140.         LicenseManager licenseManager=LicenseManagerHolder.getLicenseManager(initLicenseParams());  
  141.         LicenseContent content=buildLicenseContent();  
  142.         licenseManager.store(content, new File(licPath));  
  143.         System.out.println("证书发布成功");  
  144.     }  
  145. }  

licenseMakeConf.properties

[plain]  view plain  copy
  1. ##########common parameters###########  
  2. #私钥的别名  
  3. private.key.alias=privatekey  
  4. #privateKeyPwd(该密码生成密钥对的密码,需要妥善保管,不能让使用者知道)  
  5. private.key.pwd=noryar456  
  6. #keyStorePwd(该密码是在使用keytool生成密钥对时设置的密钥库的访问密码)  
  7. key.store.pwd=noryar123  
  8. #项目的唯一识别码  
  9. subject=noryar  
  10. #生成证书的地址  
  11. licPath=license.lic  
  12. #密钥库的地址  
  13. priPath=privateKeys.store  
  14. ##########license content###########  
  15. #发布日期  
  16. issuedTime=2016-07-25  
  17. #有效开始日期  
  18. notBefore=2016-07-25  
  19. #有效截止日期  
  20. notAfter=2016-08-30  
  21. #consumerType  
  22. consumerType=user  
  23. #ConsumerAmount  
  24. consumerAmount=1  
  25. #info  
  26. info=this is a license  

测试方法

[java]  view plain  copy
  1. public static void main(String[] args) throws Exception  
  2.     {  
  3.         LicenseMake clicense=new LicenseMake("/licenseMakeConf.properties");  
  4.         clicense.create();  
  5.     }  
以上就可以创建出一个license文件了。然后开发者将license文件传递给购买方。购买方在系统中上传该文件进行验证即可。


4. 验证证书

[java]  view plain  copy
  1. package com.noryar.license;  
  2.   
  3. import de.schlichtherle.license.LicenseManager;  
  4. import de.schlichtherle.license.LicenseParam;  
  5. /** 
  6.  * 单例模式下的证书管理器 
  7.  * @author Leon Lee 
  8.  */  
  9. public class LicenseManagerHolder  
  10. {  
  11.     private static LicenseManager licenseManager;  
  12.     private LicenseManagerHolder(){}  
  13.     public static synchronized  LicenseManager getLicenseManager(LicenseParam param)  
  14.     {  
  15.         if(licenseManager==null)  
  16.         {  
  17.             licenseManager=new LicenseManager(param);  
  18.         }  
  19.         return licenseManager;  
  20.     }  
  21. }  

认证核心方法

[java]  view plain  copy
  1. package com.noryar.license;  
  2.   
  3. import java.io.File;  
  4. import java.io.IOException;  
  5. import java.io.InputStream;  
  6. import java.util.Properties;  
  7. import java.util.prefs.Preferences;  
  8.   
  9. import de.schlichtherle.license.CipherParam;  
  10. import de.schlichtherle.license.DefaultCipherParam;  
  11. import de.schlichtherle.license.DefaultKeyStoreParam;  
  12. import de.schlichtherle.license.DefaultLicenseParam;  
  13. import de.schlichtherle.license.KeyStoreParam;  
  14. import de.schlichtherle.license.LicenseContentException;  
  15. import de.schlichtherle.license.LicenseManager;  
  16. import de.schlichtherle.license.LicenseParam;  
  17.   
  18. public class LicenseVertify  
  19. {  
  20.     /** 
  21.      * 公钥别名 
  22.      */  
  23.     private String pubAlias;  
  24.     /** 
  25.      * 该密码是在使用keytool生成密钥对时设置的密钥库的访问密码  
  26.      */  
  27.     private String keyStorePwd;  
  28.     /** 
  29.      * 系统的统一识别码 
  30.      */  
  31.     private String onlykey;  
  32.     /** 
  33.      * 证书路径  
  34.      */  
  35.     private String licName;  
  36.     /** 
  37.      * 公钥库路径 
  38.      */  
  39.     private String pubPath;  
  40.     private String confPath="/licenseVertifyConf.properties";  
  41.     public LicenseVertify(String onlykey)  
  42.     {  
  43.         setConf(confPath,onlykey);  
  44.     }  
  45.       
  46.     public LicenseVertify(String confPath,String onlykey)  
  47.     {  
  48.         setConf(confPath,onlykey);  
  49.     }  
  50.     /** 
  51.      * 通过外部配置文件获取配置信息 
  52.      * @param confPath  配置文件路径 
  53.      * @param onlykey 系统的统一识别码 
  54.      */  
  55.     public void setConf(String confPath,String onlykey)  
  56.     {  
  57.         // 获取参数  
  58.         Properties prop = new Properties();  
  59.         InputStream in = getClass().getResourceAsStream(confPath);  
  60.         try  
  61.         {  
  62.             prop.load(in);  
  63.         }  
  64.         catch (IOException e)  
  65.         {  
  66.             e.printStackTrace();  
  67.         }  
  68.           
  69.         this.onlykey=onlykey;  
  70.         pubAlias = prop.getProperty("public.alias");  
  71.         keyStorePwd = prop.getProperty("key.store.pwd");  
  72.         licName = prop.getProperty("license.name");  
  73.         pubPath = prop.getProperty("public.store.path");  
  74.           
  75.     }  
  76.       
  77.     /** 
  78.      * 初始化证书的相关参数 
  79.      * @param 系统的统一识别码 
  80.      * @return 
  81.      */  
  82.     private LicenseParam initLicenseParams()  
  83.     {  
  84.         Class<LicenseVertify> clazz=LicenseVertify.class;  
  85.         Preferences pre=Preferences.userNodeForPackage(clazz);  
  86.         CipherParam cipherParam=new DefaultCipherParam(storePwd);  
  87.         KeyStoreParam pubStoreParam=new DefaultKeyStoreParam(clazz, pubPath, pubAlias, keyStorePwd, null);  
  88.         LicenseParam licenseParam=new DefaultLicenseParam(onlykey, pre, pubStoreParam, cipherParam);  
  89.         return licenseParam;  
  90.     }  
  91.       
  92.     private LicenseManager getLicenseManager()  
  93.     {  
  94.         return LicenseManagerHolder.getLicenseManager(initLicenseParams());  
  95.     }  
  96.     /** 
  97.      * 安装证书证书 
  98.      * @param 存放证书的路径 
  99.      * @return 
  100.      */  
  101.     public void install(String licdir)  
  102.     {  
  103.         try  
  104.         {  
  105.             LicenseManager licenseManager=getLicenseManager();  
  106.             licenseManager.install(new File(licdir+File.separator+licName));  
  107.             System.out.println("安装证书成功!");  
  108.         }  
  109.         catch (Exception e)  
  110.         {  
  111.             System.out.println("安装证书失败!");  
  112.             e.printStackTrace();  
  113.             System.exit(0);  
  114.         }  
  115.           
  116.     }  
  117.       
  118.     /** 
  119.      * 验证证书的合法性 
  120.      * @return 0、合法,1、证书过期,2、证书错误 
  121.      */  
  122.     public int vertify()  
  123.     {  
  124.         try  
  125.         {  
  126.             LicenseManager licenseManager=getLicenseManager();  
  127.             licenseManager.verify();  
  128.             System.out.println("验证证书成功!");  
  129.             return 0;  
  130.         }  
  131.         catch(LicenseContentException ex)  
  132.         {  
  133.             System.out.println("证书已经过期!");  
  134.             ex.printStackTrace();  
  135.             return 1;  
  136.         }  
  137.         catch (Exception e)  
  138.         {  
  139.             System.out.println("验证证书失败!");  
  140.             e.printStackTrace();  
  141.             return 2;  
  142.         }  
  143.     }  
  144. }  

测试

[java]  view plain  copy
  1. public static void main(String[] args) throws Exception  
  2.     {  
  3.         LicenseVertify vlicense=new LicenseVertify("noryar"); // 项目唯一识别码,对应生成配置文件的subject  
  4.         vlicense.install(System.getProperty("user.dir"));  
  5.         vlicense.vertify();  
  6.     }  
licenseVertifyConf.properties

[plain]  view plain  copy
  1. ##########common parameters###########  
  2. #公钥别名  
  3. public.alias=publiccert  
  4. #使用keytool生成密钥对时设置的密钥库的访问密码  
  5. key.store.pwd= noryar123  
  6. #证书路径  
  7. license.name=license.lic  
  8. #公共库路径  
  9. public.store.path=publicCerts.store  

总结

以上就是license开发的常规手段。对于web项目来说,只需要提供license认证模块的开发即可。对于开发者来说,可以将license生成单独开发一个小程序。以后就可以通过这个程序来给不同的企业生成license。

此外,为了更好的保护代码。license认证模块可以进行混淆加密,解密部分使用C语言来编写,同时针对不同的平台进行编译。增强破解难度。

版权声明:本文为博主原创文章,转载请附明出处。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值