license生成证书并校验
项目位置在文件服务器: \192.168.16.114\v3.0产品相关资源\05 预研\License证书。其中 1. license.keyPass 和license.storePass 要个第一步使用的一致。publicCerts. keystore(公钥)提供给证书认证使用。privateKeys.keystore(私钥)提供给生成证书使用。publicKeysStorePath:公钥位置
第一步:我们可以通过Jdk(建议jdk1.8)自带的keytool工具生成,进入JDK的bin目录命令行(win+r输入cmd)输入以下命令:
1. 生成命令
keytool -genkeypair -keysize 1024 -validity 3650 -alias "privateKey"
-keystore "privateKeys.keystore" -storepass "public_password1234" -keypass
"private_password1234" -dname "CN=localhost, OU=localhost, O=localhost, L=SH, ST=SH, C=CN"
参数说明
- keysize 密钥长度
- validity 私钥的有效期(单位:天)
- alias 私钥别称
- keystore 指定私钥库文件的名称 (生成在当前目录)
- storepass 指定私钥库的密码 (keystore 文件存储密码)
- keypass 指定别名条目的密码 (私钥加解密密码)
- dname 证书个人信息
CN 为你的姓名
OU 为你的组织单位名称
O 为你的组织名称
L 为你所在的城市名称
ST 为你所在的省份名称
C 为你的国家名称
生成文件如下图所示
2. 执行导出命令
keytool -import -alias "publicCert" -file "certfile.cer" -keystore "publicCerts.keystore"
-storepass "public_password1234"
参数说明:
- alias 公钥别称
- file 证书文件名称
- keystore 公钥文件名称
- storepass 指定私钥库的密码
3. 执行导入命令
keytool -import -alias "publicCert" -file "certfile.cer" -keystore "publicCerts.keystore" -storepass "public_password1234"
命令行当前路径可以看到以下三个文件:
①privateKeys.keystore(私钥)提供给生成证书使用 (生成后放在license生成项目的文件夹中,如放在部署路径的resource/key文件夹)
②publicCerts. keystore(公钥)提供给证书认证使用(要跟随部署文件一块放到部署服务器,如放在部署路径的resource/default 文件夹) 。
③certfile.cer后续步骤用不到,可以删除
第二步 生成许可证
旧版license证书生成地址: http://192.168.16.212:7000/createLicense (不带平台标识)
项目位置在文件服务器: \192.168.16.114\v3.0产品相关资源\05 预研\License证书
代码结构如下图所示:
其中yq_privateKeys.keystore 是在第一步生成的。
license配置
license.keyPass=a123456
license.storePass=a123456
license.licensePath=${user.dir}/resource/key/yq_license.lic #license证书 生成路径
license.privateKeysStorePath=${user.dir}/resource/key/yq_privateKeys.keystore # 私钥的存放路径
其中 1. license.keyPass 和license.storePass 要个第一步使用的一致。
第三步 校验许可证
、
license的公钥安放位置如下图所示。
安装路径为如下配置
license:
subject: yq_license
publicAlias: publicCert
storePass: a123456
licensePath: ${user.dir}/resource/default/yq_license.lic
publicKeysStorePath: ${user.dir}/resource/default/yq_publicCerts.keystore
subject :证书名
publicAlias:公钥别称
storePass:公钥密码
licensePath:证书文职
publicKeysStorePath:公钥位置
前端相关接口
- /license/importLicense 证书上传
- /license/installLicense 证书安装
- /license/licenseTest 证书校验
注: 以上三接口需要在shiro中配置放开token校验
license校验代码如下:
@GetMapping(value = "/licenseTest")
public Result<?> test() {
LicenseContent licenseContent = this.getLicenseContent();
try {
if ("证书合法".equals(customLicenseManager.validateCreate(licenseContent))) {
return Result.ok(customLicenseManager.validateCreate(licenseContent));
} else {
return Result.error(customLicenseManager.validateCreate(licenseContent));
}
} catch (Exception e) {
if ("exc.licenseHasExpired".equals(this.getMessage())) {
return Result.error("许可证已过期,请重新上传");
} else {
return Result.error(this.getMessage());
}
}
}
/**
* 校验生成证书的参数信息
*
* @param content 证书正文
*/
public String validateCreate(LicenseContent content) throws LicenseContentException {
final LicenseParam param = getLicenseParam();
final Date now = new Date();
final Date notBefore = content.getNotBefore();
final Date notAfter = content.getNotAfter();
final String consumerType = content.getConsumerType();
if (null != notAfter && now.after(notAfter)) {
System.out.println("证书失效时间不能早于当前时间");
// throw new LicenseContentException("证书失效时间不能早于当前时间");
return "证书已失效,请重新上传";
} else if (null != notBefore && null != notAfter && notAfter.before(notBefore)) {
System.out.println("证书生效时间不能晚于证书失效时间");
// throw new LicenseContentException("证书生效时间不能晚于证书失效时间");
return "证书生效时间不能晚于证书失效时间";
} else if (null == consumerType) {
System.out.println("用户类型不能为空");
// throw new LicenseContentException("用户类型不能为空");
return "用户类型不能为空";
}
return "证书合法";
}
/**
* 安装License证书
*/
public synchronized LicenseContent install(LicenseVerifyParam param) throws Exception {
LicenseContent result = null;
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//获取继承了LicenseManager的CustomLicenseManager的单例对象 在这里调用验证方法
LicenseManager licenseManager = LicenseManagerHolder.getInstance(initLicenseParam(param));
//1. 卸载历史证书
licenseManager.uninstall();
//2. 安装新的证书
File file = new File(param.getLicensePath());
//logger.info("授权证书安装路径 :" + file.getPath());
//此处调用 CustomLicenseManager.install(),通过重写后的方法在安装时进行部分校验
result = licenseManager.install(file);
//logger.info(MessageFormat.format("证书安装成功,证书有效期:{0} - {1}", format.format(result.getNotBefore()), format.format(result.getNotAfter())));
return result;
}
@Override
protected synchronized void validate(final LicenseContent content) throws LicenseContentException {
RedisTemplate redisTemplate = (RedisTemplate) SpringContextUtils.getBean("redisTemplate");
//1. 首先调用父类的validate方法
super.validate(content);
//2. 然后校验自定义的License参数
//License中可被允许的参数信息
LicenseCheckModel expectedCheckModel = (LicenseCheckModel) content.getExtra();
logger.info("expectedCheckModel====="+expectedCheckModel);
//从缓存中获取当前服务器真实的参数信息
LocalCacheUtils cacheUtils = LocalCacheUtils.getInstance();
LicenseCheckModel serverCheckModel = (LicenseCheckModel) cacheUtils.getValueByKey("serverInfo");
logger.info("serverCheckModel==="+serverCheckModel);
if (expectedCheckModel != null && serverCheckModel != null) {
//针对同一证书只在首次安装时校验安装时间
final Date now = new Date();
final Date installedExpiration = expectedCheckModel.getInstalledExpiration();
//判断此前是否已记录证书标识 以及 当前证书标识与此前纪录的证书标识的值是否一致
String currentLicenseCode = String.valueOf(redisTemplate.opsForValue().get("license_currentLicense"));
if (redisTemplate.hasKey("license_redisLicense")) {
String redisLicenseCode = String.valueOf(redisTemplate.opsForValue().get("license_redisLicense"));
if (!redisLicenseCode.equals(currentLicenseCode)) {
if (null != installedExpiration && now.after(installedExpiration)) {
throw new LicenseContentException("当前时间不能晚于安装截止时间");
}
}
} else {
if (null != installedExpiration && now.after(installedExpiration)) {
throw new LicenseContentException("当前时间不能晚于安装截止时间");
}
}
//授权要求IP、Mac、Sn校验值至少存在一个 且 该校验值需通过校验
if (CollectionUtils.isNotEmpty(expectedCheckModel.getIpAddress()) || CollectionUtils.isNotEmpty(expectedCheckModel.getMacAddress()) || CollectionUtils.isNotEmpty(expectedCheckModel.getMainBoardSerial())) {
//校验IP
boolean checkIpAddress = checkIpAddress(expectedCheckModel.getIpAddress(), serverCheckModel.getIpAddress());
//校验Mac
boolean checkMacAddressPre = checkMacAddressPre(expectedCheckModel.getMacAddress());
boolean checkMacAddress = checkIpAddress(expectedCheckModel.getMacAddress(), serverCheckModel.getMacAddress());
//校验MainBoardSerial
boolean checkMainBoardSerial = checkIpAddress(expectedCheckModel.getMainBoardSerial(), serverCheckModel.getMainBoardSerial());
if (!(checkIpAddress && (checkMacAddress || checkMacAddressPre) && checkMainBoardSerial)) {
throw new LicenseContentException("IP、Mac或Sn不符合授权要求");
}
} else {
throw new LicenseContentException("IP、Mac或Sn不符合授权要求");
}
//校验平台标识
if (StringUtils.isNotEmpty(expectedCheckModel.getPlatformIdentify()) && !expectedCheckModel.getPlatformIdentify().equals("sdyq-2019-yqsm-product-1.0")) {
throw new LicenseContentException("产品标识不符合授权要求");
}
//校验CPU序列号
if (!checkIpAddress(expectedCheckModel.getCpuSerial(), serverCheckModel.getCpuSerial())) {
throw new LicenseContentException("当前服务器的CPU序列号没在授权范围内");
}
//校验CPU个数
if (!checkCpus(expectedCheckModel.getCpus(), serverCheckModel.getCpus())) {
throw new LicenseContentException("当前服务器的CPU数量没在授权范围内");
}
} else {
throw new LicenseContentException("不能获取服务器硬件信息");
}
}
更多推荐
所有评论(0)