init project
This commit is contained in:
88
.gitignore
vendored
Normal file
88
.gitignore
vendored
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
######################################################################
|
||||||
|
# Build Tools
|
||||||
|
|
||||||
|
.gradle
|
||||||
|
/build/
|
||||||
|
!gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
target/
|
||||||
|
!.mvn/wrapper/maven-wrapper.jar
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# IDE
|
||||||
|
|
||||||
|
### STS ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
|
||||||
|
### IntelliJ IDEA ###
|
||||||
|
.idea
|
||||||
|
*.iws
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
|
||||||
|
### JRebel ###
|
||||||
|
rebel.xml
|
||||||
|
### NetBeans ###
|
||||||
|
nbproject/private/
|
||||||
|
build/*
|
||||||
|
nbbuild/
|
||||||
|
dist/
|
||||||
|
nbdist/
|
||||||
|
.nb-gradle/
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# Others
|
||||||
|
*.log
|
||||||
|
*.xml.versionsBackup
|
||||||
|
*.swp
|
||||||
|
*.bak
|
||||||
|
tmp
|
||||||
|
|
||||||
|
!*/build/*.java
|
||||||
|
!*/build/*.html
|
||||||
|
!*/build/*.xml
|
||||||
|
|
||||||
|
# docker
|
||||||
|
docker/mysql/data
|
||||||
|
docker/redis/data
|
||||||
|
docker/mysql/log
|
||||||
|
docker/nacos/logs
|
||||||
|
docker/mysql/db/*.sql
|
||||||
|
docker/wfc/*/jar/*.jar
|
||||||
|
docker/wfc/*/*/jar/*.jar
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
.DS_Store
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
coverage
|
||||||
|
*.local
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
|
|
||||||
|
package-lock.json
|
||||||
|
yarn.lock
|
||||||
|
|
||||||
|
.VSCodeCounter
|
||||||
178
pom.xml
Normal file
178
pom.xml
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
|
<version>2.3.0.RELEASE</version>
|
||||||
|
<relativePath/> <!-- lookup parent from repository -->
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<groupId>com.modules</groupId>
|
||||||
|
<artifactId>cloud-license-serve</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
<name>cloud-license-serve</name>
|
||||||
|
<description>license serve project</description>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<java.version>1.8</java.version>
|
||||||
|
<spring-cloud.version>Hoxton.SR3</spring-cloud.version>
|
||||||
|
</properties>
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<!-- SpringBoot 核心包 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-devtools</artifactId>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- SpringBoot 测试 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.junit.vintage</groupId>
|
||||||
|
<artifactId>junit-vintage-engine</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- lombok -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- License -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>de.schlichtherle.truelicense</groupId>
|
||||||
|
<artifactId>truelicense-core</artifactId>
|
||||||
|
<version>1.33</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.sourceforge.nekohtml</groupId>
|
||||||
|
<artifactId>nekohtml</artifactId>
|
||||||
|
<version>1.9.18</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Commons -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-lang3</artifactId>
|
||||||
|
<version>3.7</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-io</groupId>
|
||||||
|
<artifactId>commons-io</artifactId>
|
||||||
|
<version>2.6</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-codec</groupId>
|
||||||
|
<artifactId>commons-codec</artifactId>
|
||||||
|
<version>1.11</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Apache HttpClient -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
|
<artifactId>httpclient</artifactId>
|
||||||
|
<version>4.5.5</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Fastjson -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>fastjson</artifactId>
|
||||||
|
<version>1.2.47</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Java Servlet API -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.servlet</groupId>
|
||||||
|
<artifactId>javax.servlet-api</artifactId>
|
||||||
|
<version>4.0.1</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Jackson对自动解析JSON和XML格式的支持 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.jaxrs</groupId>
|
||||||
|
<artifactId>jackson-jaxrs-json-provider</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.dataformat</groupId>
|
||||||
|
<artifactId>jackson-dataformat-xml</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.junit.vintage</groupId>
|
||||||
|
<artifactId>junit-vintage-engine</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<!-- 依赖版本管理 -->
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-dependencies</artifactId>
|
||||||
|
<version>${spring-cloud.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
<!-- 引入系统范围内的依赖 -->
|
||||||
|
<configuration>
|
||||||
|
<includeSystemScope>true</includeSystemScope>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<!--添加配置跳过测试-->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>2.22.2</version>
|
||||||
|
<configuration>
|
||||||
|
<skipTests>true</skipTests>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
||||||
18
src/main/java/org/wfc/common/license/ServeApplication.java
Normal file
18
src/main/java/org/wfc/common/license/ServeApplication.java
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package org.wfc.common.license;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.boot.web.servlet.ServletComponentScan;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@SpringBootApplication
|
||||||
|
@ServletComponentScan
|
||||||
|
public class ServeApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
log.info("启动开始");
|
||||||
|
SpringApplication.run(ServeApplication.class, args);
|
||||||
|
log.info("启动成功");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package org.wfc.common.license.common.config;
|
||||||
|
|
||||||
|
import org.apache.http.Header;
|
||||||
|
import org.apache.http.client.HttpClient;
|
||||||
|
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
|
||||||
|
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
|
||||||
|
import org.apache.http.impl.client.HttpClientBuilder;
|
||||||
|
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||||
|
import org.apache.http.message.BasicHeader;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||||
|
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class RestTemplateConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回RestTemplate
|
||||||
|
*
|
||||||
|
* @param factory ClientHttpRequestFactory
|
||||||
|
* @return RestTemplate
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
|
||||||
|
return new RestTemplate(factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClientHttpRequestFactory接口的另一种实现方式(推荐使用),即:
|
||||||
|
* HttpComponentsClientHttpRequestFactory:底层使用Httpclient连接池的方式创建Http连接请求
|
||||||
|
*
|
||||||
|
* @return HttpComponentsClientHttpRequestFactory
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory() {
|
||||||
|
//Httpclient连接池,长连接保持30秒
|
||||||
|
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(30, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
//设置总连接数
|
||||||
|
connectionManager.setMaxTotal(1000);
|
||||||
|
//设置同路由的并发数
|
||||||
|
connectionManager.setDefaultMaxPerRoute(1000);
|
||||||
|
|
||||||
|
//设置header
|
||||||
|
List<Header> headers = new ArrayList<Header>();
|
||||||
|
headers.add(new BasicHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.04"));
|
||||||
|
headers.add(new BasicHeader("Accept-Encoding", "gzip, deflate"));
|
||||||
|
headers.add(new BasicHeader("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3"));
|
||||||
|
headers.add(new BasicHeader("Connection", "keep-alive"));
|
||||||
|
|
||||||
|
//创建HttpClient
|
||||||
|
HttpClient httpClient = HttpClientBuilder.create()
|
||||||
|
.setConnectionManager(connectionManager)
|
||||||
|
.setDefaultHeaders(headers)
|
||||||
|
.setRetryHandler(new DefaultHttpRequestRetryHandler(3, true)) //设置重试次数
|
||||||
|
.setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy()) //设置保持长连接
|
||||||
|
.build();
|
||||||
|
|
||||||
|
//创建HttpComponentsClientHttpRequestFactory实例
|
||||||
|
HttpComponentsClientHttpRequestFactory requestFactory =
|
||||||
|
new HttpComponentsClientHttpRequestFactory(httpClient);
|
||||||
|
|
||||||
|
//设置客户端和服务端建立连接的超时时间
|
||||||
|
requestFactory.setConnectTimeout(5000);
|
||||||
|
//设置客户端从服务端读取数据的超时时间
|
||||||
|
requestFactory.setReadTimeout(5000);
|
||||||
|
//设置从连接池获取连接的超时时间,不宜过长
|
||||||
|
requestFactory.setConnectionRequestTimeout(200);
|
||||||
|
//缓冲请求数据,默认为true。通过POST或者PUT大量发送数据时,建议将此更改为false,以免耗尽内存
|
||||||
|
requestFactory.setBufferRequestBody(false);
|
||||||
|
return requestFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
package org.wfc.common.license.common.utils;
|
||||||
|
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.ApplicationContextAware;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义Spring工具类
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class SpringContextUtils implements ApplicationContextAware {
|
||||||
|
private static ApplicationContext applicationContext;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setApplicationContext(ApplicationContext context) throws BeansException {
|
||||||
|
applicationContext = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取ApplicationContext对象
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static ApplicationContext getApplicationContext() {
|
||||||
|
return applicationContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据bean的名称获取bean
|
||||||
|
*
|
||||||
|
* @param name
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Object getBeanByName(String name) {
|
||||||
|
return applicationContext.getBean(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据bean的class来查找对象
|
||||||
|
*
|
||||||
|
* @param <T>
|
||||||
|
* @param c
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static <T> T getBeanByClass(Class<T> c) {
|
||||||
|
return applicationContext.getBean(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据bean的class来查找所有的对象(包括子类)
|
||||||
|
*
|
||||||
|
* @param <T>
|
||||||
|
* @param c
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static <T> Map<String, T> getBeansByClass(Class<T> c) {
|
||||||
|
return applicationContext.getBeansOfType(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取HttpServletRequest
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static HttpServletRequest getRequest() {
|
||||||
|
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
|
||||||
|
HttpServletRequest request = attributes.getRequest();
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
package org.wfc.common.license.controller;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import org.wfc.common.license.domain.LicenseCheckModel;
|
||||||
|
import org.wfc.common.license.domain.LicenseCreatorParam;
|
||||||
|
import org.wfc.common.license.domain.LicenseGenParam;
|
||||||
|
import org.wfc.common.license.license.AbstractServerInfos;
|
||||||
|
import org.wfc.common.license.license.LicenseCreator;
|
||||||
|
import org.wfc.common.license.license.LinuxServerInfos;
|
||||||
|
import org.wfc.common.license.license.WindowsServerInfos;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于生成证书文件,不能放在给客户部署的代码里
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/license")
|
||||||
|
public class LicenseCreatorController {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 证书生成路径
|
||||||
|
*/
|
||||||
|
@Value("${license.licensePath}")
|
||||||
|
private String licensePath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取服务器硬件信息
|
||||||
|
*
|
||||||
|
* @param osName 操作系统类型,如果为空则自动判断
|
||||||
|
* @return com.ccx.models.license.LicenseCheckModel
|
||||||
|
*/
|
||||||
|
@RequestMapping(value = "/getServerInfos", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
|
||||||
|
public LicenseCheckModel getServerInfos(@RequestParam(value = "osName", required = false) String osName) {
|
||||||
|
//操作系统类型
|
||||||
|
if (StringUtils.isBlank(osName)) {
|
||||||
|
osName = System.getProperty("os.name");
|
||||||
|
}
|
||||||
|
osName = osName.toLowerCase();
|
||||||
|
|
||||||
|
AbstractServerInfos abstractServerInfos = null;
|
||||||
|
|
||||||
|
//根据不同操作系统类型选择不同的数据获取方法
|
||||||
|
if (osName.startsWith("windows")) {
|
||||||
|
abstractServerInfos = new WindowsServerInfos();
|
||||||
|
} else if (osName.startsWith("linux")) {
|
||||||
|
abstractServerInfos = new LinuxServerInfos();
|
||||||
|
} else {//其他服务器类型
|
||||||
|
abstractServerInfos = new LinuxServerInfos();
|
||||||
|
}
|
||||||
|
return abstractServerInfos.getServerInfos();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成证书2
|
||||||
|
*
|
||||||
|
* @param param 生成证书需要的参数,如:{"subject":"ccx-models","privateAlias":"privateKey","keyPass":"5T7Zz5Y0dJFcqTxvzkH5LDGJJSGMzQ","storePass":"3538cef8e7","licensePath":"C:/Users/zifangsky/Desktop/license.lic","privateKeysStorePath":"C:/Users/zifangsky/Desktop/privateKeys.keystore","issuedTime":"2018-04-26 14:48:12","expiryTime":"2018-12-31 00:00:00","consumerType":"User","consumerAmount":1,"description":"这是证书描述信息","licenseCheckModel":{"ipAddress":["192.168.245.1","10.0.5.22"],"macAddress":["00-50-56-C0-00-01","50-7B-9D-F9-18-41"],"cpuSerial":"BFEBFBFF000406E3","mainBoardSerial":"L1HF65E00X9"}}
|
||||||
|
* @return java.util.Map<java.lang.String, java.lang.Object>
|
||||||
|
*/
|
||||||
|
@RequestMapping(value = "/generateLicense2", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
|
||||||
|
public Map<String, Object> generateLicense2(@RequestBody LicenseCreatorParam param) {
|
||||||
|
Map<String, Object> resultMap = new HashMap<>(2);
|
||||||
|
|
||||||
|
if (StringUtils.isBlank(param.getLicensePath())) {
|
||||||
|
param.setLicensePath(licensePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
LicenseCreator licenseCreator = new LicenseCreator(param);
|
||||||
|
boolean result = licenseCreator.generateLicense();
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
resultMap.put("result", "ok");
|
||||||
|
resultMap.put("msg", param);
|
||||||
|
} else {
|
||||||
|
resultMap.put("result", "error");
|
||||||
|
resultMap.put("msg", "证书文件生成失败!");
|
||||||
|
}
|
||||||
|
return resultMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成证书
|
||||||
|
*
|
||||||
|
* @param param 生成证书需要的参数
|
||||||
|
* @return java.util.Map<java.lang.String, java.lang.Object>
|
||||||
|
*/
|
||||||
|
@RequestMapping(value = "/generateLicense", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
|
||||||
|
public Map<String, Object> generateLicense(@RequestBody LicenseGenParam genParam) {
|
||||||
|
Map<String, Object> resultMap = new HashMap<>(2);
|
||||||
|
|
||||||
|
LicenseCreatorParam param = new LicenseCreatorParam();
|
||||||
|
param.setSubject("license_wfc");
|
||||||
|
param.setPrivateAlias("privateKey");
|
||||||
|
param.setKeyPass("wanfi_wfc_Admin123lic");
|
||||||
|
param.setStorePass("public_wfc_Admin123");
|
||||||
|
if (StringUtils.isBlank(genParam.getLicensePath())) {
|
||||||
|
param.setLicensePath(licensePath);
|
||||||
|
} else {
|
||||||
|
param.setLicensePath(genParam.getLicensePath());
|
||||||
|
}
|
||||||
|
// 相对路径resources资源目录
|
||||||
|
String resourcePath = getClass().getClassLoader().getResource("").getPath();
|
||||||
|
param.setPrivateKeysStorePath(resourcePath + "privateKeys.keystore");
|
||||||
|
// param.setPrivateKeysStorePath("D:\\projects\\testdir\\spring-boot2-license\\cloud-license-serve\\target\\classes\\privateCerts.keystore");
|
||||||
|
param.setIssuedTime(new Date());
|
||||||
|
param.setExpiryTime(genParam.getExpiryTime());
|
||||||
|
param.setConsumerType("user");
|
||||||
|
param.setConsumerAmount(1);
|
||||||
|
param.setDescription("这是证书描述信息");
|
||||||
|
LicenseCheckModel licenseCheckModel = new LicenseCheckModel();
|
||||||
|
licenseCheckModel.setIpAddress(genParam.getIpAddress());
|
||||||
|
licenseCheckModel.setMacAddress(genParam.getMacAddress());
|
||||||
|
licenseCheckModel.setCpuSerial(genParam.getCpuSerial());
|
||||||
|
licenseCheckModel.setMainBoardSerial(genParam.getMainBoardSerial());
|
||||||
|
param.setLicenseCheckModel(licenseCheckModel);
|
||||||
|
|
||||||
|
LicenseCreator licenseCreator = new LicenseCreator(param);
|
||||||
|
boolean result = licenseCreator.generateLicense();
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
resultMap.put("result", "ok");
|
||||||
|
resultMap.put("msg", genParam);
|
||||||
|
} else {
|
||||||
|
resultMap.put("result", "error");
|
||||||
|
resultMap.put("msg", "证书文件生成失败!");
|
||||||
|
}
|
||||||
|
return resultMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
package org.wfc.common.license.domain;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义需要校验的License参数
|
||||||
|
*/
|
||||||
|
public class LicenseCheckModel implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 8600137500316662317L;
|
||||||
|
/**
|
||||||
|
* 可被允许的IP地址
|
||||||
|
*/
|
||||||
|
private List<String> ipAddress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 可被允许的MAC地址
|
||||||
|
*/
|
||||||
|
private List<String> macAddress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 可被允许的CPU序列号
|
||||||
|
*/
|
||||||
|
private String cpuSerial;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 可被允许的主板序列号
|
||||||
|
*/
|
||||||
|
private String mainBoardSerial;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "LicenseCheckModel{" +
|
||||||
|
"ipAddress=" + ipAddress +
|
||||||
|
", macAddress=" + macAddress +
|
||||||
|
", cpuSerial='" + cpuSerial + '\'' +
|
||||||
|
", mainBoardSerial='" + mainBoardSerial + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,189 @@
|
|||||||
|
package org.wfc.common.license.domain;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* License生成类需要的参数
|
||||||
|
*/
|
||||||
|
public class LicenseCreatorParam implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -7793154252684580872L;
|
||||||
|
/**
|
||||||
|
* 证书subject
|
||||||
|
*/
|
||||||
|
private String subject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密钥别称
|
||||||
|
*/
|
||||||
|
private String privateAlias;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密钥密码(需要妥善保管,不能让使用者知道)
|
||||||
|
*/
|
||||||
|
private String keyPass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 访问秘钥库的密码
|
||||||
|
*/
|
||||||
|
private String storePass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 证书生成路径
|
||||||
|
*/
|
||||||
|
private String licensePath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密钥库存储路径
|
||||||
|
*/
|
||||||
|
private String privateKeysStorePath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 证书生效时间
|
||||||
|
*/
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
|
private Date issuedTime = new Date();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 证书失效时间
|
||||||
|
*/
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
|
private Date expiryTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户类型
|
||||||
|
*/
|
||||||
|
private String consumerType = "user";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户数量
|
||||||
|
*/
|
||||||
|
private Integer consumerAmount = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 描述信息
|
||||||
|
*/
|
||||||
|
private String description = "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 额外的服务器硬件校验信息
|
||||||
|
*/
|
||||||
|
private LicenseCheckModel licenseCheckModel;
|
||||||
|
|
||||||
|
public String getSubject() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSubject(String subject) {
|
||||||
|
this.subject = subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPrivateAlias() {
|
||||||
|
return privateAlias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrivateAlias(String privateAlias) {
|
||||||
|
this.privateAlias = privateAlias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKeyPass() {
|
||||||
|
return keyPass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKeyPass(String keyPass) {
|
||||||
|
this.keyPass = keyPass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStorePass() {
|
||||||
|
return storePass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStorePass(String storePass) {
|
||||||
|
this.storePass = storePass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLicensePath() {
|
||||||
|
return licensePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLicensePath(String licensePath) {
|
||||||
|
this.licensePath = licensePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPrivateKeysStorePath() {
|
||||||
|
return privateKeysStorePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrivateKeysStorePath(String privateKeysStorePath) {
|
||||||
|
this.privateKeysStorePath = privateKeysStorePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getIssuedTime() {
|
||||||
|
return issuedTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIssuedTime(Date issuedTime) {
|
||||||
|
this.issuedTime = issuedTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getExpiryTime() {
|
||||||
|
return expiryTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExpiryTime(Date expiryTime) {
|
||||||
|
this.expiryTime = expiryTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getConsumerType() {
|
||||||
|
return consumerType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConsumerType(String consumerType) {
|
||||||
|
this.consumerType = consumerType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getConsumerAmount() {
|
||||||
|
return consumerAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConsumerAmount(Integer consumerAmount) {
|
||||||
|
this.consumerAmount = consumerAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LicenseCheckModel getLicenseCheckModel() {
|
||||||
|
return licenseCheckModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLicenseCheckModel(LicenseCheckModel licenseCheckModel) {
|
||||||
|
this.licenseCheckModel = licenseCheckModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "LicenseCreatorParam{" +
|
||||||
|
"subject='" + subject + '\'' +
|
||||||
|
", privateAlias='" + privateAlias + '\'' +
|
||||||
|
", keyPass='" + keyPass + '\'' +
|
||||||
|
", storePass='" + storePass + '\'' +
|
||||||
|
", licensePath='" + licensePath + '\'' +
|
||||||
|
", privateKeysStorePath='" + privateKeysStorePath + '\'' +
|
||||||
|
", issuedTime=" + issuedTime +
|
||||||
|
", expiryTime=" + expiryTime +
|
||||||
|
", consumerType='" + consumerType + '\'' +
|
||||||
|
", consumerAmount=" + consumerAmount +
|
||||||
|
", description='" + description + '\'' +
|
||||||
|
", licenseCheckModel=" + licenseCheckModel +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
107
src/main/java/org/wfc/common/license/domain/LicenseGenParam.java
Normal file
107
src/main/java/org/wfc/common/license/domain/LicenseGenParam.java
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
package org.wfc.common.license.domain;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* License生成类需要的参数
|
||||||
|
*/
|
||||||
|
public class LicenseGenParam implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -7793154252684580871L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 证书生成路径
|
||||||
|
*/
|
||||||
|
private String licensePath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 证书失效时间
|
||||||
|
*/
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
|
private Date expiryTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 额外的服务器硬件校验信息
|
||||||
|
*/
|
||||||
|
private LicenseCheckModel licenseCheckModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 可被允许的IP地址
|
||||||
|
*/
|
||||||
|
private List<String> ipAddress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 可被允许的MAC地址
|
||||||
|
*/
|
||||||
|
private List<String> macAddress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 可被允许的CPU序列号
|
||||||
|
*/
|
||||||
|
private String cpuSerial;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 可被允许的主板序列号
|
||||||
|
*/
|
||||||
|
private String mainBoardSerial;
|
||||||
|
|
||||||
|
public String getLicensePath() {
|
||||||
|
return licensePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLicensePath(String licensePath) {
|
||||||
|
this.licensePath = licensePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getExpiryTime() {
|
||||||
|
return expiryTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExpiryTime(Date expiryTime) {
|
||||||
|
this.expiryTime = expiryTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LicenseCheckModel getLicenseCheckModel() {
|
||||||
|
return licenseCheckModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLicenseCheckModel(LicenseCheckModel licenseCheckModel) {
|
||||||
|
this.licenseCheckModel = licenseCheckModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
package org.wfc.common.license.license;
|
||||||
|
|
||||||
|
import org.wfc.common.license.domain.LicenseCheckModel;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于获取客户服务器的基本信息,如:IP、Mac地址、CPU序列号、主板序列号等
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public abstract class AbstractServerInfos {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组装需要额外校验的License参数
|
||||||
|
*
|
||||||
|
* @return demo.LicenseCheckModel
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public LicenseCheckModel getServerInfos() {
|
||||||
|
LicenseCheckModel result = new LicenseCheckModel();
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取IP地址
|
||||||
|
*
|
||||||
|
* @return java.util.List<java.lang.String>
|
||||||
|
*/
|
||||||
|
protected abstract List<String> getIpAddress() throws Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取Mac地址
|
||||||
|
*
|
||||||
|
* @return java.util.List<java.lang.String>
|
||||||
|
*/
|
||||||
|
protected abstract List<String> getMacAddress() throws Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取CPU序列号
|
||||||
|
*
|
||||||
|
* @return java.lang.String
|
||||||
|
*/
|
||||||
|
protected abstract String getCPUSerial() throws Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取主板序列号
|
||||||
|
*
|
||||||
|
* @return java.lang.String
|
||||||
|
*/
|
||||||
|
protected abstract String getMainBoardSerial() throws Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前服务器所有符合条件的InetAddress
|
||||||
|
*
|
||||||
|
* @return java.util.List<java.net.InetAddress>
|
||||||
|
*/
|
||||||
|
protected List<InetAddress> getLocalAllInetAddress() throws Exception {
|
||||||
|
List<InetAddress> result = new ArrayList<>(4);
|
||||||
|
|
||||||
|
// 遍历所有的网络接口
|
||||||
|
for (Enumeration networkInterfaces = NetworkInterface.getNetworkInterfaces(); networkInterfaces.hasMoreElements(); ) {
|
||||||
|
NetworkInterface iface = (NetworkInterface) networkInterfaces.nextElement();
|
||||||
|
// 在所有的接口下再遍历IP
|
||||||
|
for (Enumeration inetAddresses = iface.getInetAddresses(); inetAddresses.hasMoreElements(); ) {
|
||||||
|
InetAddress inetAddr = (InetAddress) inetAddresses.nextElement();
|
||||||
|
|
||||||
|
//排除LoopbackAddress、SiteLocalAddress、LinkLocalAddress、MulticastAddress类型的IP地址
|
||||||
|
if (!inetAddr.isLoopbackAddress() /*&& !inetAddr.isSiteLocalAddress()*/
|
||||||
|
&& !inetAddr.isLinkLocalAddress() && !inetAddr.isMulticastAddress()) {
|
||||||
|
result.add(inetAddr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取某个网络接口的Mac地址
|
||||||
|
*
|
||||||
|
* @param
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected String getMacByInetAddress(InetAddress inetAddr) {
|
||||||
|
try {
|
||||||
|
byte[] mac = NetworkInterface.getByInetAddress(inetAddr).getHardwareAddress();
|
||||||
|
StringBuffer stringBuffer = new StringBuffer();
|
||||||
|
for (int i = 0; i < mac.length; i++) {
|
||||||
|
if (i != 0) {
|
||||||
|
stringBuffer.append("-");
|
||||||
|
}
|
||||||
|
//将十六进制byte转化为字符串
|
||||||
|
String temp = Integer.toHexString(mac[i] & 0xff);
|
||||||
|
if (temp.length() == 1) {
|
||||||
|
stringBuffer.append("0" + temp);
|
||||||
|
} else {
|
||||||
|
stringBuffer.append(temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stringBuffer.toString().toUpperCase();
|
||||||
|
} catch (SocketException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
log.error("获取某个网络接口的Mac地址异常", e.getMessage());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package org.wfc.common.license.license;
|
||||||
|
|
||||||
|
import de.schlichtherle.license.AbstractKeyStoreParam;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义KeyStoreParam,用于将公私钥存储文件存放到其他磁盘位置而不是项目中
|
||||||
|
*/
|
||||||
|
public class CustomKeyStoreParam extends AbstractKeyStoreParam {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 公钥/私钥在磁盘上的存储路径
|
||||||
|
*/
|
||||||
|
private String storePath;
|
||||||
|
private String alias;
|
||||||
|
private String storePwd;
|
||||||
|
private String keyPwd;
|
||||||
|
|
||||||
|
public CustomKeyStoreParam(Class clazz, String resource, String alias, String storePwd, String keyPwd) {
|
||||||
|
super(clazz, resource);
|
||||||
|
this.storePath = resource;
|
||||||
|
this.alias = alias;
|
||||||
|
this.storePwd = storePwd;
|
||||||
|
this.keyPwd = keyPwd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAlias() {
|
||||||
|
return alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getStorePwd() {
|
||||||
|
return storePwd;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getKeyPwd() {
|
||||||
|
return keyPwd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 复写de.schlichtherle.license.AbstractKeyStoreParam的getStream()方法<br/>
|
||||||
|
* 用于将公私钥存储文件存放到其他磁盘位置而不是项目中
|
||||||
|
*
|
||||||
|
* @param
|
||||||
|
* @return java.io.InputStream
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public InputStream getStream() throws IOException {
|
||||||
|
final InputStream in = new FileInputStream(new File(storePath));
|
||||||
|
if (null == in) {
|
||||||
|
throw new FileNotFoundException(storePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,264 @@
|
|||||||
|
package org.wfc.common.license.license;
|
||||||
|
|
||||||
|
import org.wfc.common.license.domain.LicenseCheckModel;
|
||||||
|
import de.schlichtherle.license.*;
|
||||||
|
import de.schlichtherle.xml.GenericCertificate;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import java.beans.XMLDecoder;
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义LicenseManager,用于增加额外的服务器硬件信息校验
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class CustomLicenseManager extends LicenseManager {
|
||||||
|
|
||||||
|
//XML编码
|
||||||
|
private static final String XML_CHARSET = "UTF-8";
|
||||||
|
//默认BUFSIZE
|
||||||
|
private static final int DEFAULT_BUFSIZE = 8 * 1024;
|
||||||
|
|
||||||
|
public CustomLicenseManager() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public CustomLicenseManager(LicenseParam param) {
|
||||||
|
super(param);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 复写create方法
|
||||||
|
*
|
||||||
|
* @param
|
||||||
|
* @return byte[]
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected synchronized byte[] create(
|
||||||
|
LicenseContent content,
|
||||||
|
LicenseNotary notary)
|
||||||
|
throws Exception {
|
||||||
|
initialize(content);
|
||||||
|
this.validateCreate(content);
|
||||||
|
final GenericCertificate certificate = notary.sign(content);
|
||||||
|
return getPrivacyGuard().cert2key(certificate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 复写install方法,其中validate方法调用本类中的validate方法,校验IP地址、Mac地址等其他信息
|
||||||
|
*
|
||||||
|
* @param
|
||||||
|
* @return de.schlichtherle.license.LicenseContent
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected synchronized LicenseContent install(
|
||||||
|
final byte[] key,
|
||||||
|
final LicenseNotary notary)
|
||||||
|
throws Exception {
|
||||||
|
final GenericCertificate certificate = getPrivacyGuard().key2cert(key);
|
||||||
|
|
||||||
|
notary.verify(certificate);
|
||||||
|
final LicenseContent content = (LicenseContent) this.load(certificate.getEncoded());
|
||||||
|
this.validate(content);
|
||||||
|
setLicenseKey(key);
|
||||||
|
setCertificate(certificate);
|
||||||
|
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 复写verify方法,调用本类中的validate方法,校验IP地址、Mac地址等其他信息
|
||||||
|
*
|
||||||
|
* @param
|
||||||
|
* @return de.schlichtherle.license.LicenseContent
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected synchronized LicenseContent verify(final LicenseNotary notary)
|
||||||
|
throws Exception {
|
||||||
|
GenericCertificate certificate = getCertificate();
|
||||||
|
|
||||||
|
// Load license key from preferences,
|
||||||
|
final byte[] key = getLicenseKey();
|
||||||
|
if (null == key) {
|
||||||
|
throw new NoLicenseInstalledException(getLicenseParam().getSubject());
|
||||||
|
}
|
||||||
|
|
||||||
|
certificate = getPrivacyGuard().key2cert(key);
|
||||||
|
notary.verify(certificate);
|
||||||
|
final LicenseContent content = (LicenseContent) this.load(certificate.getEncoded());
|
||||||
|
this.validate(content);
|
||||||
|
setCertificate(certificate);
|
||||||
|
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验生成证书的参数信息
|
||||||
|
*
|
||||||
|
* @param content 证书正文
|
||||||
|
*/
|
||||||
|
protected synchronized void validateCreate(final LicenseContent content)
|
||||||
|
throws LicenseContentException {
|
||||||
|
final LicenseParam param = getLicenseParam();
|
||||||
|
|
||||||
|
final Date now = new Date();
|
||||||
|
final Date notBefore = content.getNotBefore();
|
||||||
|
final Date notAfter = content.getNotAfter();
|
||||||
|
if (null != notAfter && now.after(notAfter)) {
|
||||||
|
throw new LicenseContentException("证书失效时间不能早于当前时间");
|
||||||
|
}
|
||||||
|
if (null != notBefore && null != notAfter && notAfter.before(notBefore)) {
|
||||||
|
throw new LicenseContentException("证书生效时间不能晚于证书失效时间");
|
||||||
|
}
|
||||||
|
final String consumerType = content.getConsumerType();
|
||||||
|
if (null == consumerType) {
|
||||||
|
throw new LicenseContentException("用户类型不能为空");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 复写validate方法,增加IP地址、Mac地址等其他信息校验
|
||||||
|
*
|
||||||
|
* @param content LicenseContent
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected synchronized void validate(final LicenseContent content)
|
||||||
|
throws LicenseContentException {
|
||||||
|
//1. 首先调用父类的validate方法
|
||||||
|
super.validate(content);
|
||||||
|
|
||||||
|
//2. 然后校验自定义的License参数
|
||||||
|
//License中可被允许的参数信息
|
||||||
|
LicenseCheckModel expectedCheckModel = (LicenseCheckModel) content.getExtra();
|
||||||
|
//当前服务器真实的参数信息
|
||||||
|
LicenseCheckModel serverCheckModel = getServerInfos();
|
||||||
|
|
||||||
|
if (expectedCheckModel != null && serverCheckModel != null) {
|
||||||
|
//校验IP地址
|
||||||
|
if (!checkIpAddress(expectedCheckModel.getIpAddress(), serverCheckModel.getIpAddress())) {
|
||||||
|
throw new LicenseContentException("当前服务器的IP没在授权范围内");
|
||||||
|
}
|
||||||
|
|
||||||
|
//校验Mac地址
|
||||||
|
if (!checkIpAddress(expectedCheckModel.getMacAddress(), serverCheckModel.getMacAddress())) {
|
||||||
|
throw new LicenseContentException("当前服务器的Mac地址没在授权范围内");
|
||||||
|
}
|
||||||
|
|
||||||
|
//校验主板序列号
|
||||||
|
if (!checkSerial(expectedCheckModel.getMainBoardSerial(), serverCheckModel.getMainBoardSerial())) {
|
||||||
|
throw new LicenseContentException("当前服务器的主板序列号没在授权范围内");
|
||||||
|
}
|
||||||
|
|
||||||
|
//校验CPU序列号
|
||||||
|
if (!checkSerial(expectedCheckModel.getCpuSerial(), serverCheckModel.getCpuSerial())) {
|
||||||
|
throw new LicenseContentException("当前服务器的CPU序列号没在授权范围内");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new LicenseContentException("不能获取服务器硬件信息");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重写XMLDecoder解析XML
|
||||||
|
*
|
||||||
|
* @param encoded XML类型字符串
|
||||||
|
* @return java.lang.Object
|
||||||
|
*/
|
||||||
|
private Object load(String encoded) {
|
||||||
|
BufferedInputStream inputStream = null;
|
||||||
|
XMLDecoder decoder = null;
|
||||||
|
try {
|
||||||
|
inputStream = new BufferedInputStream(new ByteArrayInputStream(encoded.getBytes(XML_CHARSET)));
|
||||||
|
|
||||||
|
decoder = new XMLDecoder(new BufferedInputStream(inputStream, DEFAULT_BUFSIZE), null, null);
|
||||||
|
|
||||||
|
return decoder.readObject();
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (decoder != null) {
|
||||||
|
decoder.close();
|
||||||
|
}
|
||||||
|
if (inputStream != null) {
|
||||||
|
inputStream.close();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("XMLDecoder解析XML失败", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前服务器需要额外校验的License参数
|
||||||
|
*
|
||||||
|
* @return demo.LicenseCheckModel
|
||||||
|
*/
|
||||||
|
private LicenseCheckModel getServerInfos() {
|
||||||
|
//操作系统类型
|
||||||
|
String osName = System.getProperty("os.name").toLowerCase();
|
||||||
|
AbstractServerInfos abstractServerInfos = null;
|
||||||
|
|
||||||
|
//根据不同操作系统类型选择不同的数据获取方法
|
||||||
|
if (osName.startsWith("windows")) {
|
||||||
|
abstractServerInfos = new WindowsServerInfos();
|
||||||
|
} else if (osName.startsWith("linux")) {
|
||||||
|
abstractServerInfos = new LinuxServerInfos();
|
||||||
|
} else {//其他服务器类型
|
||||||
|
abstractServerInfos = new LinuxServerInfos();
|
||||||
|
}
|
||||||
|
|
||||||
|
return abstractServerInfos.getServerInfos();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验当前服务器的IP/Mac地址是否在可被允许的IP范围内<br/>
|
||||||
|
* 如果存在IP在可被允许的IP/Mac地址范围内,则返回true
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
private boolean checkIpAddress(List<String> expectedList, List<String> serverList) {
|
||||||
|
if (expectedList != null && expectedList.size() > 0) {
|
||||||
|
if (serverList != null && serverList.size() > 0) {
|
||||||
|
for (String expected : expectedList) {
|
||||||
|
if (serverList.contains(expected.trim())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验当前服务器硬件(主板、CPU等)序列号是否在可允许范围内
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
private boolean checkSerial(String expectedSerial, String serverSerial) {
|
||||||
|
if (StringUtils.isNotBlank(expectedSerial)) {
|
||||||
|
if (StringUtils.isNotBlank(serverSerial)) {
|
||||||
|
if (expectedSerial.equals(serverSerial)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
package org.wfc.common.license.license;
|
||||||
|
|
||||||
|
import org.wfc.common.license.domain.LicenseCreatorParam;
|
||||||
|
import de.schlichtherle.license.*;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import javax.security.auth.x500.X500Principal;
|
||||||
|
import java.io.File;
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import java.util.prefs.Preferences;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* License生成类
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class LicenseCreator {
|
||||||
|
|
||||||
|
private final static X500Principal DEFAULT_HOLDER_AND_ISSUER = new X500Principal("CN=localhost, OU=localhost, O=localhost, L=SH, ST=SH, C=CN");
|
||||||
|
private LicenseCreatorParam param;
|
||||||
|
|
||||||
|
public LicenseCreator(LicenseCreatorParam param) {
|
||||||
|
this.param = param;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成License证书
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public boolean generateLicense() {
|
||||||
|
try {
|
||||||
|
LicenseManager licenseManager = new CustomLicenseManager(initLicenseParam());
|
||||||
|
LicenseContent licenseContent = initLicenseContent();
|
||||||
|
|
||||||
|
licenseManager.store(licenseContent, new File(param.getLicensePath()));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(MessageFormat.format("证书生成失败:{0}", param), e.getMessage(), e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化证书生成参数
|
||||||
|
*
|
||||||
|
* @return de.schlichtherle.license.LicenseParam
|
||||||
|
*/
|
||||||
|
private LicenseParam initLicenseParam() {
|
||||||
|
Preferences preferences = Preferences.userNodeForPackage(LicenseCreator.class);
|
||||||
|
|
||||||
|
//设置对证书内容加密的秘钥
|
||||||
|
CipherParam cipherParam = new DefaultCipherParam(param.getStorePass());
|
||||||
|
|
||||||
|
KeyStoreParam privateStoreParam = new CustomKeyStoreParam(LicenseCreator.class
|
||||||
|
, param.getPrivateKeysStorePath()
|
||||||
|
, param.getPrivateAlias()
|
||||||
|
, param.getStorePass()
|
||||||
|
, param.getKeyPass());
|
||||||
|
|
||||||
|
LicenseParam licenseParam = new DefaultLicenseParam(param.getSubject()
|
||||||
|
, preferences
|
||||||
|
, privateStoreParam
|
||||||
|
, cipherParam);
|
||||||
|
|
||||||
|
return licenseParam;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置证书生成正文信息
|
||||||
|
*
|
||||||
|
* @return de.schlichtherle.license.LicenseContent
|
||||||
|
*/
|
||||||
|
private LicenseContent initLicenseContent() {
|
||||||
|
LicenseContent licenseContent = new LicenseContent();
|
||||||
|
licenseContent.setHolder(DEFAULT_HOLDER_AND_ISSUER);
|
||||||
|
licenseContent.setIssuer(DEFAULT_HOLDER_AND_ISSUER);
|
||||||
|
|
||||||
|
licenseContent.setSubject(param.getSubject());
|
||||||
|
licenseContent.setIssued(param.getIssuedTime());
|
||||||
|
licenseContent.setNotBefore(param.getIssuedTime());
|
||||||
|
licenseContent.setNotAfter(param.getExpiryTime());
|
||||||
|
licenseContent.setConsumerType(param.getConsumerType());
|
||||||
|
licenseContent.setConsumerAmount(param.getConsumerAmount());
|
||||||
|
licenseContent.setInfo(param.getDescription());
|
||||||
|
|
||||||
|
//扩展校验服务器硬件信息
|
||||||
|
licenseContent.setExtra(param.getLicenseCheckModel());
|
||||||
|
|
||||||
|
return licenseContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
package org.wfc.common.license.license;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于获取客户Linux服务器的基本信息
|
||||||
|
*/
|
||||||
|
public class LinuxServerInfos extends AbstractServerInfos {
|
||||||
|
|
||||||
|
@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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,144 @@
|
|||||||
|
package org.wfc.common.license.license;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Scanner;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于获取客户Windows服务器的基本信息
|
||||||
|
*/
|
||||||
|
public class WindowsServerInfos extends AbstractServerInfos {
|
||||||
|
|
||||||
|
@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;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getCPUSerial2() 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 != null && scanner.hasNext()) {
|
||||||
|
scanner.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scanner.hasNext()) {
|
||||||
|
serialNumber = scanner.next().trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
scanner.close();
|
||||||
|
return serialNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getCPUSerial() throws Exception {
|
||||||
|
String result = "";
|
||||||
|
try {
|
||||||
|
File file = File.createTempFile("tmp", ".vbs");
|
||||||
|
file.deleteOnExit();
|
||||||
|
FileWriter fw = new FileWriter(file);
|
||||||
|
String vbs = "Set objWMIService = GetObject(\"winmgmts:\\\\.\\root\\cimv2\")\n"
|
||||||
|
+ "Set colItems = objWMIService.ExecQuery _ \n" + " (\"Select * from Win32_Processor\") \n"
|
||||||
|
+ "For Each objItem in colItems \n" + " Wscript.Echo objItem.ProcessorId \n"
|
||||||
|
+ " exit for ' do the first cpu only! \n" + "Next \n";
|
||||||
|
|
||||||
|
fw.write(vbs);
|
||||||
|
fw.close();
|
||||||
|
Process p = Runtime.getRuntime().exec("cscript //NoLogo " + file.getPath());
|
||||||
|
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||||
|
String line;
|
||||||
|
while ((line = input.readLine()) != null) {
|
||||||
|
result += line;
|
||||||
|
}
|
||||||
|
input.close();
|
||||||
|
file.delete();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return getCPUSerial2();
|
||||||
|
}
|
||||||
|
return result.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getMainBoardSerial2() 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 != null && scanner.hasNext()) {
|
||||||
|
scanner.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scanner.hasNext()) {
|
||||||
|
serialNumber = scanner.next().trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
scanner.close();
|
||||||
|
return serialNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getMainBoardSerial() throws Exception {
|
||||||
|
|
||||||
|
String result = "";
|
||||||
|
try {
|
||||||
|
File file = File.createTempFile("realhowto", ".vbs");
|
||||||
|
file.deleteOnExit();
|
||||||
|
FileWriter fw = new FileWriter(file);
|
||||||
|
|
||||||
|
String vbs = "Set objWMIService = GetObject(\"winmgmts:\\\\.\\root\\cimv2\")\n"
|
||||||
|
+ "Set colItems = objWMIService.ExecQuery _ \n" + " (\"Select * from Win32_BaseBoard\") \n"
|
||||||
|
+ "For Each objItem in colItems \n" + " Wscript.Echo objItem.SerialNumber \n"
|
||||||
|
+ " exit for ' do the first cpu only! \n" + "Next \n";
|
||||||
|
|
||||||
|
fw.write(vbs);
|
||||||
|
fw.close();
|
||||||
|
Process p = Runtime.getRuntime().exec("cscript //NoLogo " + file.getPath());
|
||||||
|
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||||
|
String line;
|
||||||
|
while ((line = input.readLine()) != null) {
|
||||||
|
result += line;
|
||||||
|
}
|
||||||
|
input.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return getMainBoardSerial2();
|
||||||
|
}
|
||||||
|
return result.trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
10
src/main/resources/application.properties
Normal file
10
src/main/resources/application.properties
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
server.port=8081
|
||||||
|
|
||||||
|
#<23><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Źػ<C5B9>
|
||||||
|
server.shutdown=graceful
|
||||||
|
#<23><><EFBFBD><EFBFBD>10<31><30>
|
||||||
|
spring.lifecycle.timeout-per-shutdown-phase=10s
|
||||||
|
|
||||||
|
#License<73><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
license.licensePath=/opt/license/license.lic
|
||||||
|
|
||||||
23
src/main/resources/banner.txt
Normal file
23
src/main/resources/banner.txt
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
${AnsiColor.BRIGHT_YELLOW}Spring Boot: ${spring-boot.formatted-version}
|
||||||
|
${AnsiColor.BRIGHT_GREEN}$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
|
||||||
|
${AnsiColor.BRIGHT_YELLOW}$$ _.ooOoo._ $$
|
||||||
|
${AnsiColor.BRIGHT_RED}$$ o888888888o $$
|
||||||
|
${AnsiColor.BRIGHT_CYAN}$$ 88" . "88 $$
|
||||||
|
${AnsiColor.BRIGHT_MAGENTA}$$ (| ^_^ |) $$
|
||||||
|
${AnsiColor.BRIGHT_GREEN}$$ O\ = /O $$
|
||||||
|
${AnsiColor.BRIGHT_RED}$$ ____/`-----'\____ $$
|
||||||
|
${AnsiColor.BRIGHT_CYAN}$$ .' \\| |$$ `. $$
|
||||||
|
${AnsiColor.BRIGHT_MAGENTA}$$ / \\||| : |||$$ \ $$
|
||||||
|
${AnsiColor.BRIGHT_GREEN}$$ / _||||| -:- |||||- \ $$
|
||||||
|
${AnsiColor.BRIGHT_YELLOW}$$ | | \\\ - $$/ | | $$
|
||||||
|
${AnsiColor.BRIGHT_GREEN}$$ | \_| ''\-----/'' | | $$
|
||||||
|
${AnsiColor.BRIGHT_YELLOW}$$ \ .-\___ `-` ____/-. / $$
|
||||||
|
${AnsiColor.BRIGHT_CYAN}$$ ___`. .' /--.--\ `. . ___ $$
|
||||||
|
${AnsiColor.BRIGHT_RED}$$ ."" '< `.____\_<|>_/____.' >'"". $$
|
||||||
|
${AnsiColor.BRIGHT_GREEN}$$ | | : `- \`.;`.\ _ /``;.`/ - ` : | | $$
|
||||||
|
${AnsiColor.BRIGHT_YELLOW}$$ \ \ `-. \_ ___\ /___ _/ .-` / / $$
|
||||||
|
${AnsiColor.BRIGHT_CYAN}$$ ========`-.____`-.____\_____/____.-`____.-'======== $$
|
||||||
|
${AnsiColor.BRIGHT_MAGENTA}$$ `=---=' $$
|
||||||
|
${AnsiColor.BRIGHT_YELLOW}$$ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ $$
|
||||||
|
${AnsiColor.BRIGHT_GREEN}$$ 佛祖保佑 永无BUG 永不修改 $$
|
||||||
|
${AnsiColor.BRIGHT_YELLOW}$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
|
||||||
BIN
src/main/resources/privateKeys.keystore
Normal file
BIN
src/main/resources/privateKeys.keystore
Normal file
Binary file not shown.
Reference in New Issue
Block a user