证书认证

new
parent 4c136402bd
commit c478a70bef

@ -38,6 +38,7 @@
<revision>1.7.3-snapshot</revision>
<!-- Maven 相关 -->
<java.version>1.8</java.version>
<truelicense>1.33</truelicense>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<maven-surefire-plugin.version>3.0.0-M5</maven-surefire-plugin.version>

@ -21,6 +21,15 @@
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
<dependencies>
<!-- License -->
<dependency>
<groupId>de.schlichtherle.truelicense</groupId>
<artifactId>truelicense-core</artifactId>
<version>${truelicense}</version>
</dependency>
<!-- 报销系统业务 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>

@ -2,6 +2,7 @@ package cn.iocoder.yudao.server;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.PropertySource;
/**
*
@ -26,9 +27,6 @@ public class YudaoServerApplication {
// .applicationStartup(new BufferingApplicationStartup(20480))
// .run(args);
// 如果你碰到启动的问题,请认真阅读 https://doc.iocoder.cn/quick-start/ 文章
// 如果你碰到启动的问题,请认真阅读 https://doc.iocoder.cn/quick-start/ 文章
// 如果你碰到启动的问题,请认真阅读 https://doc.iocoder.cn/quick-start/ 文章
}
}

@ -0,0 +1,144 @@
package cn.iocoder.yudao.server.license;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
/**
* IPMacCPU
*
* @author zifangsky
* @date 2018/4/23
* @since 1.0.0
*/
public abstract class AbstractServerInfos {
private static Logger logger = LogManager.getLogger(AbstractServerInfos.class);
/**
* License
* @author zifangsky
* @date 2018/4/23 14:23
* @since 1.0.0
* @return demo.LicenseCheckModel
*/
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){
logger.error("获取服务器硬件信息失败",e);
}
return result;
}
/**
* IP
* @author zifangsky
* @date 2018/4/23 11:32
* @since 1.0.0
* @return java.util.List<java.lang.String>
*/
protected abstract List<String> getIpAddress() throws Exception;
/**
* Mac
* @author zifangsky
* @date 2018/4/23 11:32
* @since 1.0.0
* @return java.util.List<java.lang.String>
*/
protected abstract List<String> getMacAddress() throws Exception;
/**
* CPU
* @author zifangsky
* @date 2018/4/23 11:35
* @since 1.0.0
* @return java.lang.String
*/
protected abstract String getCPUSerial() throws Exception;
/**
*
* @author zifangsky
* @date 2018/4/23 11:35
* @since 1.0.0
* @return java.lang.String
*/
protected abstract String getMainBoardSerial() throws Exception;
/**
* InetAddress
* @author zifangsky
* @date 2018/4/23 17:38
* @since 1.0.0
* @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
* @author zifangsky
* @date 2018/4/23 18:08
* @since 1.0.0
* @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();
}
return null;
}
}

@ -0,0 +1,66 @@
package cn.iocoder.yudao.server.license;
import de.schlichtherle.license.AbstractKeyStoreParam;
import java.io.*;
/**
* KeyStoreParam
*
* @author zifangsky
* @date 2018/4/26
* @since 1.0.0
*/
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.AbstractKeyStoreParamgetStream()<br/>
*
* @author zifangsky
* @date 2018/4/26 18:28
* @since 1.0.0
* @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,288 @@
package cn.iocoder.yudao.server.license;
import de.schlichtherle.license.*;
import de.schlichtherle.xml.GenericCertificate;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.NotNull;
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
*
* @author zifangsky
* @date 2018/4/23
* @since 1.0.0
*/
public class CustomLicenseManager extends LicenseManager{
private static Logger logger = LogManager.getLogger(CustomLicenseManager.class);
//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
* @author zifangsky
* @date 2018/4/23 10:36
* @since 1.0.0
* @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);
}
/**
* installvalidatevalidateIPMac
* @author zifangsky
* @date 2018/4/23 10:40
* @since 1.0.0
* @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;
}
/**
* verifyvalidateIPMac
* @author zifangsky
* @date 2018/4/23 10:40
* @since 1.0.0
* @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;
}
/**
*
* @author zifangsky
* @date 2018/5/2 15:43
* @since 1.0.0
* @param content
*/
protected synchronized void validateCreate(@NotNull 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("用户类型不能为空");
}
}
/**
* validateIPMac
* @author zifangsky
* @date 2018/4/23 10:40
* @since 1.0.0
* @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("不能获取服务器硬件信息");
}
}
/**
* XMLDecoderXML
* @author zifangsky
* @date 2018/4/25 14:02
* @since 1.0.0
* @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) {
logger.error("XMLDecoder解析XML失败",e);
}
}
return null;
}
/**
* License
* @author zifangsky
* @date 2018/4/23 14:33
* @since 1.0.0
* @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/MacIP<br/>
* IPIP/Mactrue
* @author zifangsky
* @date 2018/4/24 11:44
* @since 1.0.0
* @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
* @author zifangsky
* @date 2018/4/24 14:38
* @since 1.0.0
* @param
* @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,43 @@
package cn.iocoder.yudao.server.license;
import com.alibaba.fastjson.JSON;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
/**
* LicenseCheckInterceptor
*
* @author zifangsky
* @date 2018/4/25
* @since 1.0.0
*/
public class LicenseCheckInterceptor extends HandlerInterceptorAdapter{
private static Logger logger = LogManager.getLogger(LicenseCheckInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
LicenseVerify licenseVerify = new LicenseVerify();
//校验证书是否有效
boolean verifyResult = licenseVerify.verify();
if(verifyResult){
return true;
}else{
Map<String,String> result = new HashMap<>(1);
result.put("result","您的证书无效,请核查服务器是否取得授权或重新申请证书!");
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write(JSON.toJSONString(result));
return false;
}
}
}

@ -0,0 +1,76 @@
package cn.iocoder.yudao.server.license;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
/**
*
*
* @author zifangsky
* @date 2018/4/24
* @since 1.0.0
*/
@Component
public class LicenseCheckListener implements ApplicationListener<ContextRefreshedEvent> {
private static Logger logger = LogManager.getLogger(LicenseCheckListener.class);
/**
* subject
*/
@Value("${license.subject}")
private String subject;
/**
*
*/
@Value("${license.publicAlias}")
private String publicAlias;
/**
* 访
*/
@Value("${license.storePass}")
private String storePass;
/**
*
*/
@Value("${license.licensePath}")
private String licensePath;
/**
*
*/
@Value("${license.publicKeysStorePath}")
private String publicKeysStorePath;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
//root application context 没有parent
ApplicationContext context = event.getApplicationContext().getParent();
if(context == null){
if(StringUtils.isNotBlank(licensePath)){
logger.info("++++++++ 开始安装证书 ++++++++");
LicenseVerifyParam param = new LicenseVerifyParam();
param.setSubject(subject);
param.setPublicAlias(publicAlias);
param.setStorePass(storePass);
param.setLicensePath(licensePath);
param.setPublicKeysStorePath(publicKeysStorePath);
LicenseVerify licenseVerify = new LicenseVerify();
//安装证书
licenseVerify.install(param);
logger.info("++++++++ 证书安装结束 ++++++++");
}
}
}
}

@ -0,0 +1,40 @@
package cn.iocoder.yudao.server.license;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* License
*
* @author zifangsky
* @date 2018/4/23
* @since 1.0.0
*/
@Data
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;
}

@ -0,0 +1,29 @@
package cn.iocoder.yudao.server.license;
import de.schlichtherle.license.LicenseManager;
import de.schlichtherle.license.LicenseParam;
/**
* de.schlichtherle.license.LicenseManager
*
* @author zifangsky
* @date 2018/4/19
* @since 1.0.0
*/
public class LicenseManagerHolder {
private static volatile LicenseManager LICENSE_MANAGER;
public static LicenseManager getInstance(LicenseParam param){
if(LICENSE_MANAGER == null){
synchronized (LicenseManagerHolder.class){
if(LICENSE_MANAGER == null){
LICENSE_MANAGER = new CustomLicenseManager(param);
}
}
}
return LICENSE_MANAGER;
}
}

@ -0,0 +1,96 @@
package cn.iocoder.yudao.server.license;
import de.schlichtherle.license.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.File;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.prefs.Preferences;
/**
* License
*
* @author zifangsky
* @date 2018/4/20
* @since 1.0.0
*/
public class LicenseVerify {
private static Logger logger = LogManager.getLogger(LicenseVerify.class);
/**
* License
* @author zifangsky
* @date 2018/4/20 16:26
* @since 1.0.0
*/
public synchronized LicenseContent install(LicenseVerifyParam param){
LicenseContent result = null;
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//1. 安装证书
try{
LicenseManager licenseManager = LicenseManagerHolder.getInstance(initLicenseParam(param));
licenseManager.uninstall();
result = licenseManager.install(new File(param.getLicensePath()));
logger.info(MessageFormat.format("证书安装成功,证书有效期:{0} - {1}",format.format(result.getNotBefore()),format.format(result.getNotAfter())));
}catch (Exception e){
logger.error("证书安装失败!",e);
}
return result;
}
/**
* License
* @author zifangsky
* @date 2018/4/20 16:26
* @since 1.0.0
* @return boolean
*/
public boolean verify(){
LicenseManager licenseManager = LicenseManagerHolder.getInstance(null);
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//2. 校验证书
try {
LicenseContent licenseContent = licenseManager.verify();
// System.out.println(licenseContent.getSubject());
logger.info(MessageFormat.format("证书校验通过,证书有效期:{0} - {1}",format.format(licenseContent.getNotBefore()),format.format(licenseContent.getNotAfter())));
return true;
}catch (Exception e){
logger.error("证书校验失败!",e);
return false;
}
}
/**
*
* @author zifangsky
* @date 2018/4/20 10:56
* @since 1.0.0
* @param param License
* @return de.schlichtherle.license.LicenseParam
*/
private LicenseParam initLicenseParam(LicenseVerifyParam param){
Preferences preferences = Preferences.userNodeForPackage(LicenseVerify.class);
CipherParam cipherParam = new DefaultCipherParam(param.getStorePass());
KeyStoreParam publicStoreParam = new CustomKeyStoreParam(LicenseVerify.class
,param.getPublicKeysStorePath()
,param.getPublicAlias()
,param.getStorePass()
,null);
return new DefaultLicenseParam(param.getSubject()
,preferences
,publicStoreParam
,cipherParam);
}
}

@ -0,0 +1,101 @@
package cn.iocoder.yudao.server.license;
import lombok.Data;
/**
* License
*
* @author zifangsky
* @date 2018/4/20
* @since 1.0.0
*/
public class LicenseVerifyParam {
/**
* subject
*/
private String subject;
/**
*
*/
private String publicAlias;
/**
* 访
*/
private String storePass;
/**
*
*/
private String licensePath;
/**
*
*/
private String publicKeysStorePath;
public LicenseVerifyParam() {
}
public LicenseVerifyParam(String subject, String publicAlias, String storePass, String licensePath, String publicKeysStorePath) {
this.subject = subject;
this.publicAlias = publicAlias;
this.storePass = storePass;
this.licensePath = licensePath;
this.publicKeysStorePath = publicKeysStorePath;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getPublicAlias() {
return publicAlias;
}
public void setPublicAlias(String publicAlias) {
this.publicAlias = publicAlias;
}
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 getPublicKeysStorePath() {
return publicKeysStorePath;
}
public void setPublicKeysStorePath(String publicKeysStorePath) {
this.publicKeysStorePath = publicKeysStorePath;
}
@Override
public String toString() {
return "LicenseVerifyParam{" +
"subject='" + subject + '\'' +
", publicAlias='" + publicAlias + '\'' +
", storePass='" + storePass + '\'' +
", licensePath='" + licensePath + '\'' +
", publicKeysStorePath='" + publicKeysStorePath + '\'' +
'}';
}
}

@ -0,0 +1,90 @@
package cn.iocoder.yudao.server.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
*
* @author zifangsky
* @date 2018/4/23
* @since 1.0.0
*/
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,89 @@
package cn.iocoder.yudao.server.license;
import java.net.InetAddress;
import java.util.List;
import java.util.Scanner;
import java.util.stream.Collectors;
/**
* Windows
*
* @author zifangsky
* @date 2018/4/23
* @since 1.0.0
*/
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;
}
@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 != null && 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 != null && scanner.hasNext()){
scanner.next();
}
if(scanner.hasNext()){
serialNumber = scanner.next().trim();
}
scanner.close();
return serialNumber;
}
}

@ -0,0 +1,72 @@
package cn.iocoder.yudao.server.license.common;
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
* @author zifangsky
*/
@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;
}
/**
* beanbean
* @param name
* @return
*/
public static Object getBeanByName(String name){
return applicationContext.getBean(name);
}
/**
* beanclass
* @param <T>
* @param c
* @return
*/
public static <T> T getBeanByClass(Class<T> c){
return applicationContext.getBean(c);
}
/**
* beanclass
* @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,94 @@
package cn.iocoder.yudao.server.license.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
* SimpleClientHttpRequestFactory使java.netHttp
* @return
*/
// @Bean
// public SimpleClientHttpRequestFactory simpleClientHttpRequestFactory(){
// SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
//
// requestFactory.setReadTimeout(5000);
// requestFactory.setConnectTimeout(5000);
//
// return requestFactory;
// }
/**
* ClientHttpRequestFactory使
* HttpComponentsClientHttpRequestFactory使HttpclientHttp
* @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,35 @@
package cn.iocoder.yudao.server.license.config;
import cn.iocoder.yudao.server.license.LicenseCheckInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* Web
* @author zifangsky
* @date 2018/7/9
* @since 1.0.0
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
/**
*
*/
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/index").setViewName("index");
registry.addViewController("/login").setViewName("login");
}
/**
*
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LicenseCheckInterceptor()).addPathPatterns("/admin-api/system/auth/login");
}
}

@ -195,3 +195,10 @@ wx:
host: 127.0.0.1
port: 6379
password:
license:
subject: license_demo
publicAlias: publicCert
storePass: public_password1234
licensePath: D:/license.lic
publicKeysStorePath: D:/publicCerts.keystore

@ -235,3 +235,11 @@ mybatis-plus:
flowable:
async-executor-activate: false #关闭定时任务JOB
# 将databaseSchemaUpdate设置为true。当Flowable发现库与数据库表结构不一致时会自动将数据库表结构升级至新版本。
license:
subject: license_demo
publicAlias: publicCert
storePass: public_password1234
licensePath: D:/license.lic
publicKeysStorePath: D:/publicCerts.keystore

Loading…
Cancel
Save