license验证

main
768863620@qq.com 2024-05-22 15:14:41 +08:00
parent 46b4452278
commit 46444ae1a2
96 changed files with 567 additions and 4 deletions

View File

@ -28,11 +28,19 @@ import org.springframework.stereotype.Component;
@Data
@Component
public class RsaProperties {
public static String privateKey;
public static String licenseKey;
@Value("${rsa.private_key}")
public void setPrivateKey(String privateKey) {
RsaProperties.privateKey = privateKey;
}
@Value("${rsa.licenseKey}")
public void setLicenseKey(String privateKey) {
RsaProperties.licenseKey = privateKey;
}
}

View File

@ -15,9 +15,12 @@
*/
package com.youchain;
import cn.hutool.json.JSONUtil;
import com.youchain.annotation.rest.AnonymousGetMapping;
import com.youchain.modules.license.LicenseValidate;
import com.youchain.utils.SpringContextHolder;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@ -46,7 +49,7 @@ import org.springframework.web.bind.annotation.RestController;
@EnableTransactionManagement
//@EnableAutoConfiguration(exclude={MongoAutoConfiguration.class})
@EnableJpaAuditing(auditorAwareRef = "auditorAware")
@Slf4j
public class AppRun {
public static void main(String[] args) {
@ -56,6 +59,7 @@ public class AppRun {
springApplication.addListeners(new ApplicationPidFileWriter());
springApplication.run(args);
log.error(JSONUtil.toJsonStr(LicenseValidate.getDeviceInfo()));
}

View File

@ -25,7 +25,6 @@ import com.youchain.basicdata.service.dto.StockSmallDto;
import com.youchain.businessdata.ReturnJson.RPTaskList;
import com.youchain.businessdata.inputJson.IPTask;
import com.youchain.utils.*;
import jdk.internal.dynalink.beans.StaticClass;
import lombok.RequiredArgsConstructor;
import com.youchain.basicdata.repository.PointRepository;
import com.youchain.basicdata.service.PointService;

View File

@ -0,0 +1,107 @@
package com.youchain.modules.license;
import com.youchain.modules.license.domain.LicenseCheck;
import lombok.extern.slf4j.Slf4j;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
@Slf4j
public abstract class AGxServerInfos {
/**
* <p>License</p>
*/
public LicenseCheck getServerInfos(){
LicenseCheck result = new LicenseCheck();
try {
result.setIpAddress(this.getIpAddress());
result.setMacAddress(this.getMacAddress());
result.setCpuSerial(this.getCPUSerial());
result.setMainBoardSerial(this.getMainBoardSerial());
}catch (Exception e){
log.error("获取服务器硬件信息失败",e);
}
return result;
}
/**
* <p>IP</p>
*/
protected abstract List<String> getIpAddress() throws Exception;
/**
* <p>Mac</p>
*/
protected abstract List<String> getMacAddress() throws Exception;
/**
* <p>CPU</p>
*/
protected abstract String getCPUSerial() throws Exception;
/**
* <p></p>
*/
protected abstract String getMainBoardSerial() throws Exception;
/**
* <p>InetAddress</p>
*/
protected List<InetAddress> getLocalAllInetAddress() throws Exception {
List<InetAddress> result = new ArrayList<>(4);
// 遍历所有的网络接口
for (Enumeration networkInterfaces = NetworkInterface.getNetworkInterfaces(); networkInterfaces.hasMoreElements(); ) {
NetworkInterface ni = (NetworkInterface) networkInterfaces.nextElement();
// 在所有的接口下再遍历IP
for (Enumeration addresses = ni.getInetAddresses(); addresses.hasMoreElements(); ) {
InetAddress address = (InetAddress) addresses.nextElement();
//排除LoopbackAddress、SiteLocalAddress、LinkLocalAddress、MulticastAddress类型的IP地址
if(!address.isLoopbackAddress() /*&& !inetAddr.isSiteLocalAddress()*/
&& !address.isLinkLocalAddress() && !address.isMulticastAddress()){
result.add(address);
}
}
}
return result;
}
/**
* <p>Mac</p>
*/
protected String getMacByInetAddress(InetAddress inetAddr){
try {
byte[] mac = NetworkInterface.getByInetAddress(inetAddr).getHardwareAddress();
StringBuffer sb = new StringBuffer();
for(int i=0;i<mac.length;i++){
if(i != 0) {
sb.append("-");
}
//将十六进制byte转化为字符串
String temp = Integer.toHexString(mac[i] & 0xff);
if(temp.length() == 1){
sb.append("0" + temp);
}else{
sb.append(temp);
}
}
return sb.toString().toUpperCase();
} catch (SocketException e) {
e.printStackTrace();
}
return null;
}
}

View File

@ -0,0 +1,167 @@
package com.youchain.modules.license;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.file.FileReader;
import cn.hutool.core.io.file.FileWriter;
import cn.hutool.json.JSONUtil;
import com.youchain.config.FileProperties;
import com.youchain.config.RsaProperties;
import com.youchain.exception.BadRequestException;
import com.youchain.modules.license.domain.LicenseCheck;
import com.youchain.utils.RsaUtils;
import com.youchain.utils.SpringContextHolder;
import lombok.extern.slf4j.Slf4j;
import java.util.Arrays;
import java.util.Date;
@Slf4j
public class LicenseValidate {
public static void validate() throws Exception{
//读取本地文件
FileProperties properties= SpringContextHolder.getBean(FileProperties.class);
log.info(properties.getPath().getPath());
String result="";
try{
FileReader fileReader = new FileReader(properties.getPath().getPath()+"key/"+"license.key");
result = fileReader.readString();
}catch (Exception e){
throw new BadRequestException("License不存在,请上传License");
}
log.error(result);
String rsaResult= RsaUtils.decryptByPublicKey(RsaProperties.licenseKey,result);
log.error("------------------------解密完成-----------------------");
LicenseCheck key_price = JSONUtil.toBean(rsaResult, LicenseCheck.class);
LicenseCheck system_price = getDeviceInfo();
boolean isEQ_ipAddress=Arrays.equals(key_price.getIpAddress().toArray(),system_price.getIpAddress().toArray());
if(isEQ_ipAddress){
log.error("IP匹配成功");
}else{
log.error("IP匹配失败");
throw new BadRequestException("IP匹配失败");
}
boolean isEQ_macAddress=Arrays.equals(key_price.getMacAddress().toArray(),system_price.getMacAddress().toArray());
if(isEQ_macAddress){
log.error("MAC匹配成功");
}else{
log.error("MAC匹配失败");
throw new BadRequestException("MAC匹配失败");
}
if(key_price.getMainBoardSerial().equals(system_price.getMainBoardSerial())){
log.error("主板匹配成功");
}else{
log.error("主板匹配失败");
throw new BadRequestException("主板匹配失败");
}
if(key_price.getCpuSerial().equals(system_price.getCpuSerial())){
log.error("CPU匹配成功");
}else{
log.error("CPU匹配失败");
throw new BadRequestException("CPU匹配失败");
}
try{
Date end_date = DateUtil.parse(key_price.getEndTime());
Date now_date = DateUtil.date();
if(end_date.before(now_date)){
throw new BadRequestException("过期的License,请重新生成");
}else{
log.error("有效期验证通过");
}
}catch (Exception e){
throw new BadRequestException("无效的License,请重新生成");
}
}
public static void saveCode(String license_code) throws Exception{
//读取本地文件
log.error(license_code);
String rsaResult="";
try{
rsaResult= RsaUtils.decryptByPublicKey(RsaProperties.licenseKey,license_code);
}catch (Exception e){
throw new BadRequestException("License无效请重新生成");
}
log.error("解密完成");
log.error(rsaResult);
LicenseCheck key_price = JSONUtil.toBean(rsaResult, LicenseCheck.class);
LicenseCheck system_price = getDeviceInfo();
boolean isEQ_ipAddress=Arrays.equals(key_price.getIpAddress().toArray(),system_price.getIpAddress().toArray());
if(isEQ_ipAddress){
log.error("IP匹配成功");
}else{
log.error("IP匹配失败");
throw new BadRequestException("IP匹配失败");
}
boolean isEQ_macAddress=Arrays.equals(key_price.getMacAddress().toArray(),system_price.getMacAddress().toArray());
if(isEQ_macAddress){
log.error("MAC匹配成功");
}else{
log.error("MAC匹配失败");
throw new BadRequestException("MAC匹配失败");
}
if(key_price.getMainBoardSerial().equals(system_price.getMainBoardSerial())){
log.error("主板匹配成功");
}else{
log.error("主板匹配失败");
throw new BadRequestException("主板匹配失败");
}
if(key_price.getCpuSerial().equals(system_price.getCpuSerial())){
log.error("CPU匹配成功");
}else{
log.error("CPU匹配失败");
throw new BadRequestException("CPU匹配失败");
}
try{
Date end_date = DateUtil.parse(key_price.getEndTime());
Date now_date = DateUtil.date();
if(end_date.before(now_date)){
throw new BadRequestException("过期的License,请重新生成");
}else{
log.error("有效期验证通过");
}
}catch (Exception e){
throw new BadRequestException("无效的License,请重新生成");
}
FileProperties properties= SpringContextHolder.getBean(FileProperties.class);
log.info(properties.getPath().getPath());
FileWriter writer = new FileWriter(properties.getPath().getPath()+"key/"+"license.key");
writer.write(license_code);
}
public static LicenseCheck getDeviceInfo(){
String osName = System.getProperty("os.name");
osName = osName.toLowerCase();
AGxServerInfos abstractServerInfos;
//根据不同操作系统类型选择不同的数据获取方法
if (osName.startsWith("windows")) {
abstractServerInfos = new WindowsServerInfos();
} else if (osName.startsWith("linux")) {
abstractServerInfos = new LinuxServerInfos();
}else{//其他服务器类型
abstractServerInfos = new LinuxServerInfos();
}
return abstractServerInfos.getServerInfos();
}
}

View File

@ -0,0 +1,86 @@
package com.youchain.modules.license;
import com.youchain.utils.StringUtils;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.util.List;
import java.util.stream.Collectors;
/**
* <p>Linux</p>
*/
public class LinuxServerInfos extends AGxServerInfos {
@Override
protected List<String> getIpAddress() throws Exception {
List<String> result = null;
//获取所有网络接口
List<InetAddress> inetAddresses = getLocalAllInetAddress();
if(inetAddresses != null && inetAddresses.size() > 0){
result = inetAddresses.stream().map(InetAddress::getHostAddress).distinct().map(String::toLowerCase).collect(Collectors.toList());
}
return result;
}
@Override
protected List<String> getMacAddress() throws Exception {
List<String> result = null;
//1. 获取所有网络接口
List<InetAddress> inetAddresses = getLocalAllInetAddress();
if(inetAddresses != null && inetAddresses.size() > 0){
//2. 获取所有网络接口的Mac地址
result = inetAddresses.stream().map(this::getMacByInetAddress).distinct().collect(Collectors.toList());
}
return result;
}
@Override
protected String getCPUSerial() throws Exception {
//序列号
String serialNumber = "";
//使用dmidecode命令获取CPU序列号
String[] shell = {"/bin/bash","-c","dmidecode -t processor | grep 'ID' | awk -F ':' '{print $2}' | head -n 1"};
Process process = Runtime.getRuntime().exec(shell);
process.getOutputStream().close();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = reader.readLine().trim();
if(StringUtils.isNotBlank(line)){
serialNumber = line;
}
reader.close();
return serialNumber;
}
@Override
protected String getMainBoardSerial() throws Exception {
//序列号
String serialNumber = "";
//使用dmidecode命令获取主板序列号
String[] shell = {"/bin/bash","-c","dmidecode | grep 'Serial Number' | awk -F ':' '{print $2}' | head -n 1"};
Process process = Runtime.getRuntime().exec(shell);
process.getOutputStream().close();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = reader.readLine().trim();
if(StringUtils.isNotBlank(line)){
serialNumber = line;
}
reader.close();
return serialNumber;
}
}

View File

@ -0,0 +1,87 @@
package com.youchain.modules.license;
import java.net.InetAddress;
import java.util.List;
import java.util.Scanner;
import java.util.stream.Collectors;
/**
* <p>Windows</p>
*/
public class WindowsServerInfos extends AGxServerInfos {
@Override
protected List<String> getIpAddress() throws Exception {
List<String> result = null;
//获取所有网络接口
List<InetAddress> inetAddresses = getLocalAllInetAddress();
if(inetAddresses != null && inetAddresses.size() > 0){
result = inetAddresses.stream().map(InetAddress::getHostAddress).distinct().map(String::toLowerCase).collect(Collectors.toList());
}
return result;
}
@Override
protected List<String> getMacAddress() throws Exception {
List<String> result = null;
//1. 获取所有网络接口
List<InetAddress> inetAddresses = getLocalAllInetAddress();
if(inetAddresses != null && inetAddresses.size() > 0){
//2. 获取所有网络接口的Mac地址
result = inetAddresses.stream().map(this::getMacByInetAddress).distinct().collect(Collectors.toList());
}
return result;
}
@Override
protected String getCPUSerial() throws Exception {
//序列号
String serialNumber = "";
//使用WMIC获取CPU序列号
Process process = Runtime.getRuntime().exec("wmic cpu get processorid");
process.getOutputStream().close();
Scanner scanner = new Scanner(process.getInputStream());
if(scanner.hasNext()){
scanner.next();
}
if(scanner.hasNext()){
serialNumber = scanner.next().trim();
}
scanner.close();
return serialNumber;
}
@Override
protected String getMainBoardSerial() throws Exception {
//序列号
String serialNumber = "";
//使用WMIC获取主板序列号
Process process = Runtime.getRuntime().exec("wmic baseboard get serialnumber");
process.getOutputStream().close();
Scanner scanner = new Scanner(process.getInputStream());
if(scanner.hasNext()){
scanner.next();
}
if(scanner.hasNext()){
serialNumber = scanner.next().trim();
}
scanner.close();
return serialNumber;
}
}

View File

@ -0,0 +1,74 @@
package com.youchain.modules.license.domain;
import java.io.Serializable;
import java.util.List;
public class LicenseCheck implements Serializable {
/**
* IP
*/
private List<String> ipAddress;
/**
* mac
*/
private List<String> macAddress;
/**
* CPU
*/
private String cpuSerial;
/**
*
*/
private String mainBoardSerial;
/**
*
*/
private String endTime;
public String getEndTime() {
return endTime;
}
public void setEndTime(String endTime) {
this.endTime = endTime;
}
public LicenseCheck(){
}
public List<String> getIpAddress() {
return ipAddress;
}
public void setIpAddress(List<String> ipAddress) {
this.ipAddress = ipAddress;
}
public List<String> getMacAddress() {
return macAddress;
}
public void setMacAddress(List<String> macAddress) {
this.macAddress = macAddress;
}
public String getCpuSerial() {
return cpuSerial;
}
public void setCpuSerial(String cpuSerial) {
this.cpuSerial = cpuSerial;
}
public String getMainBoardSerial() {
return mainBoardSerial;
}
public void setMainBoardSerial(String mainBoardSerial) {
this.mainBoardSerial = mainBoardSerial;
}
}

View File

@ -16,7 +16,10 @@
package com.youchain.modules.security.rest;
import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONUtil;
import com.wf.captcha.base.Captcha;
import com.youchain.modules.license.LicenseValidate;
import com.youchain.modules.license.domain.LicenseCheck;
import com.youchain.modules.security.config.bean.LoginCodeEnum;
import com.youchain.modules.security.config.bean.SecurityProperties;
import com.youchain.modules.security.service.dto.AuthAppUserDto;
@ -39,6 +42,7 @@ import com.youchain.modules.security.service.OnlineUserService;
import com.youchain.utils.RsaUtils;
import com.youchain.utils.RedisUtils;
import com.youchain.utils.StringUtils;
import org.apache.commons.codec.binary.Base64;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@ -76,6 +80,9 @@ public class AuthorizationController {
@ApiOperation("登录授权")
@AnonymousPostMapping(value = "/login")
public ResponseEntity<Object> login(@Validated @RequestBody AuthUserDto authUser, HttpServletRequest request) throws Exception {
//验证Licens 是否有效
LicenseValidate.validate();
// 密码解密
String password = RsaUtils.decryptByPrivateKey(RsaProperties.privateKey, authUser.getPassword());
// 查询验证码
@ -117,6 +124,9 @@ public class AuthorizationController {
@ApiOperation("登录授权")
@AnonymousPostMapping(value = "/login2")
public ResponseEntity<Object> login2(@Validated @RequestBody AuthUserDto authUser, HttpServletRequest request) throws Exception {
//验证Licens 是否有效
LicenseValidate.validate();
// 密码解密
String password = authUser.getPassword();
// 查询验证码
@ -161,6 +171,9 @@ public class AuthorizationController {
@ApiOperation("App登录授权")
@AnonymousPostMapping(value = "/app_login")
public ResponseEntity<Object> app_login(@Validated @RequestBody AuthAppUserDto authUser, HttpServletRequest request) throws Exception {
//验证Licens 是否有效
LicenseValidate.validate();
// 密码解密
String password = RsaUtils.decryptByPrivateKey(RsaProperties.privateKey, authUser.getPassword());
@ -189,6 +202,23 @@ public class AuthorizationController {
return ResponseEntity.ok(authInfo);
}
@ApiOperation("获取服务器信息")
@AnonymousGetMapping(value = "/deviceinfo")
public ResponseEntity<Object> getDeviceInfo() {
LicenseCheck licenseCheck= LicenseValidate.getDeviceInfo();
String rest= Base64.encodeBase64String(JSONUtil.toJsonStr(licenseCheck).trim().getBytes());
return ResponseEntity.ok(rest);
}
@AnonymousPostMapping(value = "/createLicense")
@ApiOperation("上传License")
public ResponseEntity<Object> createNo(@RequestBody String code) throws Exception {
LicenseValidate.saveCode(code);
return ResponseEntity.ok("");
}
@ApiOperation("获取用户信息")
@GetMapping(value = "/info")
public ResponseEntity<Object> getUserInfo() {

View File

@ -1,5 +1,5 @@
server:
port: 8000
port: 8010
spring:
main:
allow-circular-references: true
@ -74,3 +74,4 @@ code:
#密码加密传输,前端公钥加密,后端私钥解密
rsa:
private_key: MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdbHkB8mp0f3FE0GYP3AYPaJF7jUd1M0XxFSE2ceK3k2kw20YvQ09NJKk+OMjWQl9WitG9pB6tSCQIDAQABAkA2SimBrWC2/wvauBuYqjCFwLvYiRYqZKThUS3MZlebXJiLB+Ue/gUifAAKIg1avttUZsHBHrop4qfJCwAI0+YRAiEA+W3NK/RaXtnRqmoUUkb59zsZUBLpvZgQPfj1MhyHDz0CIQDYhsAhPJ3mgS64NbUZmGWuuNKp5coY2GIj/zYDMJp6vQIgUueLFXv/eZ1ekgz2Oi67MNCk5jeTF2BurZqNLR3MSmUCIFT3Q6uHMtsB9Eha4u7hS31tj1UWE+D+ADzp59MGnoftAiBeHT7gDMuqeJHPL4b+kC+gzV4FGTfhR9q3tTbklZkD2A==
licenseKey: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxZQwZ6yk55wG10wn1Id34avNXV2VHf4tHM2zRolkfbOKHDRCiv32zMfELIIW91CtzB+1X/u1+3CDl2hDuYPphqLukTyp/1rKoLRoVYnWu2Ti2L+6tiwZMc5AfylAponRA/tSa3ttk+5DebaPOIk9iUTMmDpMR3SBwHGFacU6qWCR1mKxiOk78OL9nC/r24XzfvmWjvcbXs7If9F5ND2VS9e5WeOv6yMFuXSh/V5qZAkyDbEV76Tto21nLuNFLUD3iNcUYeyrns8D9UAIdDtp4sUvIADBnWlVtXNt+68a8BnlYptvpW9m0MCJZlmIzxAQY4RrpHnXF29yQB9AuPwjzwIDAQAB