# truelicense应用 **Repository Path**: zhhongyu_admin/license-verify ## Basic Information - **Project Name**: truelicense应用 - **Description**: 基于springboot构建的应用证书授权验证服务 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 5 - **Forks**: 19 - **Created**: 2020-04-28 - **Last Updated**: 2022-03-08 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # truelicense框架应用 ### 介绍 基于springboot构建的应用证书授权验证服务 ### 数字证书 ###### 入门博客参考 [数字证书](https://blog.csdn.net/zlh313_01/article/details/81114853) [代码如诗-数字证书](https://www.cnblogs.com/kex1n/p/8367373.html) ###### 使用java命令行生成密钥库 依赖jdk的keytool命令 1. 生成私钥库: ```java keytool -genkeypair -keysize 1024 -validity 3650 -alias "privateKey" -keystore "privateKeys.keystore" -storepass "renxin123" -keypass "renxin123" -dname "CN=littleutry, OU=utry, O=hy, L=HZ, ST=ZJ, C=CN" ``` **命令参数说明:** | **参数** | **说明** | **备注** | | --- | --- | --- | | keysize | 生成密钥长度 | 请务必设为1024 | | validity | 密钥有效期(单位:天) | 生成证书时证书有效期不应大于密钥有效期 | | alias | 私钥别名 | | | keystore | 生成私钥库的文件名 | | | storepass | 私钥库口令 | 必须为小写字母和数字组合,否则程序校验不通过 | | keypass | 密钥口令 | 保持与私钥库口令一致,否则解密证书会出现问题 | | dname | 密钥的Distinguished name | 程序生成证书会用到 | 2. 导出公钥证书文件 ```java keytool -exportcert -alias "privateKey" -keystore "privateKeys.keystore" -storepass "renxin123" -file "certfile.cer" ``` **命令参数说明:** | **参数** | **说明** | **备注** | | --- | --- | --- | | alias | 私钥别名 | | | keystore | 上一步生成的私钥库的文件名 | | | storepass | 私钥库口令 | 上一步设置的私钥库文件名 | | file | 导出后的的公钥证书文件名 | | 3. 将公钥证书导入公钥库 ```java keytool -import -alias "publicCert" -file "certfile.cer" -keystore "publicCerts.keystore" -storepass "renxin123" ``` **命令参数说明:** | **参数** | **说明** | **备注** | | --- | --- | --- | | alias | 公钥别名 | | | file | 要导入的公钥文件 | | | keystore | 要导入的公钥库的文件名 | | | storepass | 公钥库口令,保持与第一步设置的私钥库口令一致,否则证书安装将不通过 | | ### 工程简介 1. 工程结构 使用springboot1.5.21构建web工程 完整代码见:[license-verify](https://gitee.com/zhiliangfzhi) license-server工程使用swagger在线文档,工程启动后访问host:port/doc.html查看接口文档 * license-verify 父工程,抽取公共依赖 * license-common 公共模块,提供扩展校验逻辑接口 * license-server 授权证书颁发服务,提供接口用于生成并下载数字证书 * license-client 授权引入数字证书授权案例工程 * keystore 示例工程默认使用的密钥库文件 ### 使用说明 ##### 生成密钥库 按前述步骤生成两个密钥库文件privateKeys.keystore和publicCerts.keystore,详细记录相关参数。 ##### 使用license-server工程生成证书 1. 将私钥库文件privateKeys.keystore,拷贝到/resource/license/privateKeys.keystore 2. 按注释完善核心配置文件/resource/license/config.properties,该配置文件对应配置类是com.utry.license.server.license.LicenseConfigBean 3. 启动工程,按接口文档(host:port/doc.html)提示创建并下载生成的证书文件,保存好证书文件待用 **注意!务必仔细阅读接口文档** ##### license-client工程验证证书有效性 该工程是一个示例工程,用以指导为应用程序引入证书校验功能,引入步骤如下 1. 首先引入license-common模块依赖包(license-client已经引入); 2. 工程启动类上使用注解@ComponentScan(basePackages = {"com.utry.license.common.verify","com.utry.license.client"})将证书校验功能引入; 3. 将公钥库文件publicCerts.keystore拷贝到/resource/license/publicCerts.keystore,将证书文件拷贝到/resource/license/license.lic 4. 按注释提示完善核心配置文件/resource/license/config.properties的配置,该配置文件对应配置类是com.utry.license.common.verify.LicenseConfigBean ##### license-common模块抽取公共逻辑,可用于扩展校验逻辑 该模块功能主要是有: * 校验功能核心配置读取 * 证书有效性以及扩展参数(IP地址、mac地址等)的校验。 * 自定义扩展: * 实现com.utry.license.common.verify.CustomLicenseVerifier接口,在customVerify方法中书写扩展校验逻辑 * 将该实现类的bean注入spring容器即可 扩展校验参数为com.utry.license.common.ExtraLicenseContent的customContent字段 ### 使用过程中其他问题 **Q1** **为什么将私钥库密码、公钥库密码、私钥密码设为一致且必须为小写字母和数字组合?** **A1** 公私密钥库密码不统一将导致证书文件解密失败,这个坑很大,因为异常信息是在jdk解密工具包抛出,很难联想到需要公私钥库不统一。 **Q2** **如何扩展校验逻辑?** **A2** 如何扩展,前面已有说明,这里重点说一下,重写customVerify方法扩展了spring容器启动过程中和定时校验证书有效性的逻辑,其他细粒度权限校验, 如接口权限等的校验需要自己扩展接口拦截器,注入DefaultLicenseVerifier通过它的getCustomLicenseContent方法可获得自定义扩展校验参数。 **Q3** **为什么限制扩展参数长度?** **A3** 所有校验参数最终都被truelicense框架序列化为xml字符串,经过私钥加密生成证书文件,使用证书时需要以字节数组形式读入证书文件,truelicense框架限制最大读入1024*1024大小的证书文件, 非对称加解密本身消耗系统资源比较大,因此不建议使用太庞大的扩展参数最终导致证书文件过大。 ### 其他问题 1. 有关证书使用者修改服务器时间会导致证书有效期校验不准确问题 答:目前证书校验逻辑中是取系统时间和证书解密后包含的有效时间段做了对比,因此若使用者修改系统时间使之偏离正常时间确实会导致校验不准确问题。 由于我们的程序除从系统获取时间外不能从其他渠道获取到时间,因此要避免这个问题,只能考虑其他时间校验方式,比如校验证书的使用时长,起始三十天,使用过程中。