目标:
项目部署到服务器上,需要当前服务器授权后才能正常访问,控制项目授权日期、(某终端/通道)授权数量、用户登录访问菜单权限
注:
授权端:授权工具在自己手里,控制授权,在此我称之为授权工具
被授权端:jar包部署的服务器端,在此我称之为服务器
思路:
使用RSA-2048非对称加密方式,生成两对公钥私钥,公钥加密、私钥解密。
A公钥加密服务器的硬件信息生成机器码,
授权工具端通过上传A私钥文件解密服务器机器码。
获取到服务器硬件信息,再拼接有效日期、终端授权数量、菜单权限,授权工具端通过B公钥加密拼接内容生成授权License文件和授权记录(日志)文件。
服务器通过上传授权License文件,获取授权,使用时,通过B私钥解密并解析服务器硬件信息、有效日期、终端授权数量、菜单权限
步骤:
生成公钥私钥:
import sun.misc.BASE64Encoder;
import java.io.File;
import java.io.IOException;
import java.security.*;
/**
* @Author: Ocean
* @Date: 2021/4/7 15:27
*/
public class KeyPairGenarete {
/** 算法名称 */
private static final String ALGORITHM = "RSA";
/** 密钥长度 */
private static final int KEY_SIZE = 2048;
public static void main(String[] args) throws Exception {
// 随机生成一对密钥(包含公钥和私钥)
KeyPair keyPair = KeyPairGenarete.generateKeyPair();
// 获取 公钥 和 私钥
PublicKey pubKey = keyPair.getPublic();
PrivateKey priKey = keyPair.getPrivate();
// 保存 公钥 和 私钥
KeyPairGenarete.saveKeyForEncodedBase64(pubKey, Constants.CLIENTPUBLICKEY_FILEPATH);
KeyPairGenarete.saveKeyForEncodedBase64(priKey, Constants.CLIENTPRIVATEKEY_FILEPATH);
}
/**
* 随机生成密钥对(包含公钥和私钥)
* @return
*/
public static KeyPair generateKeyPair() throws Exception {
// 获取指定算法的密钥对生成器
KeyPairGenerator gen = KeyPairGenerator.getInstance(ALGORITHM);
// 初始化密钥对生成器(指定密钥长度, 使用默认的安全随机数源)
gen.initialize(KEY_SIZE);
// 随机生成一对密钥(包含公钥和私钥)
return gen.generateKeyPair();
}
/**
* 将 公钥/私钥 编码后以 Base64 的格式保存到指定文件
* @param key
* @param keyFile
* @throws IOException
*/
public static void saveKeyForEncodedBase64(Key key, String keyFile) throws IOException {
// 获取密钥编码后的格式
byte[] encBytes = key.getEncoded();
// 转换为 Base64 文本
String encBase64 = new BASE64Encoder().encode(encBytes);
// 保存到文件
IOUtils.writeFile(encBase64, new File(keyFile));
}
}
A公钥加密服务器的硬件信息生成机器码、前端通过接口复制机器码:
提供四种硬件信息可以随意选取拼接
package com.vikor.gateway.utils.license;
import org.springframework.beans.factory.annotation.Value;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.InputStreamReader;
import static com.vikor.gateway.utils.license.Constants.CTClientPublicKey;
import static com.vikor.gateway.utils.license.Constants.CTServerPrivateKey;
/**
* @Author: Ocean
* @Date: 2021/3/30 14:54
*/
public class LicenseCode {
/**
* 获取机器码
* @param no 硬件信息
* @return 加密后的硬件信息
*/
public static String getApplyCode(String no){
try {//通过硬件信息+A公钥=加密后的硬件信息
return RsaKey.Encrypt(no,CTClientPublicKey);
} catch (Exception e) {
e.printStackTrace();
}
return "缺少生成机器码相关文件";
}
/**
* 拼接硬件信息字符串,用其他方式拼接也可以
* @return
*/
public static String getBaseCode(){
//cpu
String CPU = getCPUSerial();
//主板
String boardSN = getMotherboardSN();
StringBuilder sb =