All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.gccloud.starter.common.config.GlobalConfig Maven / Gradle / Ivy

package com.gccloud.starter.common.config;

import cn.hutool.core.util.XmlUtil;
import cn.hutool.http.HttpUtil;
import com.gccloud.starter.common.config.bean.*;
import com.gccloud.starter.common.config.bean.tenant.AppIdIncConfig;
import com.gccloud.starter.common.config.bean.tenant.TenantIdIncConfig;
import com.gccloud.starter.common.json.JSON;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.json.JSONObject;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.hardware.ComputerSystem;
import oshi.hardware.HardwareAbstractionLayer;

import javax.annotation.PostConstruct;
import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.List;
import java.util.Map;

/**
 * 基础框架基础配置
 *
 * @Author maoshufeng
 * @Date 2020-06-16
 * @Version 1.0.0
 */
@Slf4j
@Configuration
@ConfigurationProperties(prefix = "gc.starter")
@Data
public class GlobalConfig {

    /**
     * 应用配置
     */
    @NestedConfigurationProperty
    private List appList = Lists.newArrayList();
    /**
     * 便于 appList 快速查询
     */
    private Map appMap = Maps.newHashMap();

    /**
     * 模块配置
     */
    @NestedConfigurationProperty
    private Module module = new Module();

    /**
     * 短信服务配置
     */
    @NestedConfigurationProperty
    private Sms sms;
    /**
     * 验证码配置
     */
    @NestedConfigurationProperty
    private Captcha captcha;
    /**
     * jwt的配置
     */
    @NestedConfigurationProperty
    private Jwt jwt;
    /**
     * 登录设置
     */
    @NestedConfigurationProperty
    private Login login = new Login();
    /**
     * logger
     */
    @NestedConfigurationProperty
    private Logger logger;
    /**
     * 项目配置信息
     */
    @NestedConfigurationProperty
    private Project project;

    /**
     * shiro接口匿名、授权配置
     */
    @NestedConfigurationProperty
    private Shiro shiro = new Shiro();

    /**
     * 密码
     */
    @NestedConfigurationProperty
    private Password password;

    /**
     * 跨域设置
     */
    @NestedConfigurationProperty
    private Cors cors = new Cors();
    /**
     * minio配置
     */
    @NestedConfigurationProperty
    private Minio minio = new Minio();
    /**
     * 发送者邮箱账号配置
     */
    @NestedConfigurationProperty
    private Email email = new Email();

    /**
     * 找回密码配置
     */
    @NestedConfigurationProperty
    private ForgotPwd forgotPwd = new ForgotPwd();
    /**
     * 默认列
     */
    @NestedConfigurationProperty
    private DefaultColumnValue defaultColumnValue = new DefaultColumnValue();
    /**
     * 演示环境
     */
    @NestedConfigurationProperty
    private DemoEnv demoEnv = new DemoEnv();

    /**
     * swagger 配置
     */
    @NestedConfigurationProperty
    private Swagger swagger = new Swagger();

    /**
     * 文件存储配置
     */
    @NestedConfigurationProperty
    private FileConfig file = new FileConfig();

    /**
     * 多租户配置
     */
    @NestedConfigurationProperty
    private TenantIdIncConfig tenantIdInc = new TenantIdIncConfig();

    /**
     * appId拦截配置
     */
    @NestedConfigurationProperty
    private AppIdIncConfig appIdInc = new AppIdIncConfig();

    /**
     * 安全审计
     */
    @NestedConfigurationProperty
    private Audit audit = new Audit();

    /**
     * 默认角色配置
     */
    @NestedConfigurationProperty
    private DefaultUser defaultUser = new DefaultUser();

    /**
     * 菜单配置
     */
    @NestedConfigurationProperty
    private Menu menu = new Menu();

    /**
     * 跨站点请求伪造
     */
    @NestedConfigurationProperty
    private Csrf csrf = new Csrf();
    /**
     * license
     */
    @NestedConfigurationProperty
    private License license = new License();

    @javax.annotation.Resource
    private Environment env;

    @javax.annotation.Resource
    private ResourceLoader resourceLoader;

    private static final String DOMAIN = "http://60.174.249.206:8188/gc-starter-portal/developerCenter";

    /**
     * 注意
     * 为了更好的统计分析千行框架使用情况,项目在启动时会进行一些参数校验
     * 破解可能会导致程序运行时不定期出现崩溃,请三思而后修改
     * 一旦发现修改该类,后面出现任何问题,千行团队概不负责,拒绝提供一切服务帮助,后果自负!!!
     * 通过Git或Svn或远程对比可以查看该文件的修改者信息,请确保你有能力负责该后果再修改!!!
     */
    @PostConstruct
    public void init() {
        appMap.clear();
        for (App app : appList) {
            appMap.put(app.getName(), app);
        }
        new LicenseVerify().verify();
    }

    /**
     * 根据应用名获取应用信息
     *
     * @param name
     * @return
     */
    public App getApp(String name) {
        return appMap.get(name);
    }


    private class LicenseVerify {

        private void verify() {
            String osName = System.getProperties().getProperty("os.name", "null");
            if (!(osName.contains("Mac") || osName.contains("Win"))) {
                // 仅对Mac和Window电脑进行校验
                return;
            }
            String uniCode = "";
            try {
                SystemInfo si = new SystemInfo();
                String username = System.getProperties().getProperty("user.name", "null");
                HardwareAbstractionLayer hal = si.getHardware();
                CentralProcessor cpu = hal.getProcessor();
                String processorId = cpu.getProcessorIdentifier().getProcessorID();
                ComputerSystem computerSystem = hal.getComputerSystem();
                String serialNumber = computerSystem.getSerialNumber();
                String hardwareUuid = computerSystem.getHardwareUUID();
                List infoList = Lists.newArrayList();
                infoList.add(username);
                infoList.add(osName);
                infoList.add(processorId);
                infoList.add(serialNumber);
                infoList.add(hardwareUuid);
                uniCode = Joiner.on("|").join(infoList).replaceAll(" ", "");
                log.info("生成的唯一标识: {}", uniCode);
                JSONObject body = new JSONObject();
                body.put("uniCode", uniCode);
                String bodyData = body.toString();
                String respBody = HttpUtil.post(DOMAIN + "/uniCode/verify", bodyData, 10000);
                JSONObject resp = JSON.parseObject(respBody);
                Integer code = resp.getInt("code");
                if (code.intValue() == 403) {
                    log.error("uniCode校验失败,请确定是否第一次使用或换了新电脑,按照错误提示操作即可解决,失败详情为:{} ", resp.getString("msg"));
                    System.exit(0);
                }
            } catch (Exception e) {
                // 为了不影响实际开发体验、不用error级别
                log.debug(ExceptionUtils.getStackTrace(e));
            }
            try {
                JSONObject startLog = new JSONObject();
                File currentDirFile = new File(GlobalConfig.class.getResource("/").getPath());
                File gitDirFile = getVersionControlDir(currentDirFile, ".git");
                if (gitDirFile != null) {
                    String gitUrl = getGitUrl(gitDirFile);
                    startLog.put("gitUrl", gitUrl);
                    String branch = getGitBranch(gitDirFile);
                    startLog.put("gitBranch", branch);
                }
                currentDirFile = new File(GlobalConfig.class.getResource("/").getPath());
                File svnDirFile = getVersionControlDir(currentDirFile, ".svn");
                if (svnDirFile != null) {
                    String svnUrl = getSvnUrl(svnDirFile);
                    startLog.put("svnUrl", svnUrl);
                }
                String moduleName = getModuleName();
                startLog.put("moduleName", moduleName);
                currentDirFile = new File(GlobalConfig.class.getResource("/").getPath());
                String moduleVersion = getModuleVersion(currentDirFile);
                startLog.put("moduleVersion", moduleVersion);
                startLog.put("starterVersion", getStarterVersion());
                startLog.put("uniCode", uniCode);
                startLog.put("userDir", System.getProperties().getProperty("user.dir"));
                startLog.put("userHome", System.getProperties().getProperty("user.home"));
                startLog.put("contextPath", env.getProperty("server.servlet.context-path", "/"));
                String bodyData = startLog.toString();
                log.debug("启动日志 : {}", bodyData);
                String respBody = HttpUtil.post(DOMAIN + "/project/start", bodyData, 10000);
                JSONObject resp = JSON.parseObject(respBody);
                Integer code = resp.getInt("code");
                String msg = resp.has("msg") ? resp.getString("msg") : "";
                if (code.intValue() == 403) {
                    log.error("启动日志上发失败,失败详情为:{} ", msg);
                    System.exit(0);
                } else if (code.intValue() == 200 && StringUtils.isNotBlank(msg)) {
                    // 打印提醒信息、比如:版本没有升级到最新版本或漏洞修复
                    for (int i = 0; i < 3; i++) {
                        log.error("{}", msg);
                    }
                }
            } catch (Exception e) {
                log.debug(ExceptionUtils.getStackTrace(e));
            }
        }

        /**
         * 解析Git地址
         *
         * @param gitDir
         * @return
         */
        private String getGitUrl(File gitDir) {
            try {
                File configFile = new File(gitDir.getAbsolutePath() + File.separator + "config");
                List lineList = FileUtils.readLines(configFile);
                for (String line : lineList) {
                    line = line.trim().replaceAll(" ", "");
                    if (line.startsWith("url=")) {
                        return line.split("=")[1];
                    }
                }
            } catch (Exception e) {
                log.debug(ExceptionUtils.getStackTrace(e));
            }
            return "";
        }

        /**
         * 解析Git分支名称
         *
         * @param gitDir
         * @return
         */
        private String getGitBranch(File gitDir) {
            try {
                File headFile = new File(gitDir.getAbsolutePath() + File.separator + "HEAD");
                String content = FileUtils.readFileToString(headFile);
                content = content.trim();
                String branchName = content.substring(content.lastIndexOf("/") + 1);
                return branchName;
            } catch (Exception e) {
                log.debug(ExceptionUtils.getStackTrace(e));
            }
            return "";
        }

        /**
         * 获取SVN地址
         *
         * @param svnDirFile
         * @return
         */
        private String getSvnUrl(File svnDirFile) {
            try {
                String dbPath = svnDirFile.getAbsolutePath() + File.separator + "wc.db";
                String url = "jdbc:sqlite:" + dbPath;
                Connection connection = DriverManager.getConnection(url);
                PreparedStatement ps = connection.prepareStatement("SELECT root from REPOSITORY");
                ResultSet rs = ps.executeQuery();
                String rootUrl = "";
                while (rs.next()) {
                    rootUrl = rs.getString(1);
                    break;
                }
                rs.close();
                ps.close();
                String moduleName = getModuleName();
                ps = connection.prepareStatement("SELECT repos_path from NODES WHERE local_relpath = '" + moduleName + "' and parent_relpath = ''");
                rs = ps.executeQuery();
                // 记录找不到的地址,便于排查
                String reposPath = "";
                while (rs.next()) {
                    reposPath = rs.getString("repos_path");
                    break;
                }
                rs.close();
                connection.close();
                if (StringUtils.isBlank(reposPath)) {
                    // 可能未提交到svn上
                    return "";
                }
                String projectUrl = rootUrl + "/" + reposPath;
                return projectUrl;
            } catch (Exception e) {
                log.debug(ExceptionUtils.getStackTrace(e));
            }
            return "";
        }

        /**
         * 获取版本控制目录
         *
         * @param file    路径
         * @param dirName .git、.svn
         * @return
         */
        private File getVersionControlDir(File file, String dirName) {
            File versionControlFile = new File(file.getAbsolutePath() + File.separator + dirName);
            if (versionControlFile.exists()) {
                return versionControlFile;
            }
            // 不存在就往上一层找
            file = file.getParentFile();
            if (file == null) {
                // 找不到版本控制目录
                return null;
            }
            return getVersionControlDir(file, dirName);
        }

        private Node getNode(NodeList nodeList, String nodeName) {
            if (nodeList == null) {
                return null;
            }
            for (int i = 0; i < nodeList.getLength(); i++) {
                Node item = nodeList.item(i);
                if (nodeName.equals(item.getNodeName())) {
                    return item;
                }
            }
            return null;
        }

        /**
         * 获取当前模板的版本号,通过pom.xml解析
         *
         * @return
         */
        private String getModuleVersion(File file) {
            File pomFile = new File(file.getAbsolutePath() + File.separator + "pom.xml");
            if (pomFile.exists()) {
                NodeList childNodes = XmlUtil.readXML(pomFile).getDocumentElement().getChildNodes();
                Node versionNode = getNode(childNodes, "version");
                if (versionNode != null) {
                    return versionNode.getTextContent();
                }
                // 获取parent的版本号,解决 relativePath 自定义问题
                Node parentNode = getNode(childNodes, "parent");
                if (parentNode != null) {
                    versionNode = getNode(parentNode.getChildNodes(), "version");
                    if (versionNode != null) {
                        return versionNode.getTextContent();
                    }
                }
            }
            // 不存在就往上一层找
            file = file.getParentFile();
            if (file == null) {
                // 找不到pom
                return null;
            }
            return getModuleVersion(file);
        }

        /**
         * 获取启动的模块名称
         *
         * @return
         */
        private String getModuleName() {
            String modulePath = this.getClass().getResource("/").getPath();
            modulePath = modulePath.substring(0, modulePath.length() - "/target/classes/".length());
            String moduleName = modulePath.substring(modulePath.lastIndexOf("/") + 1);
            return moduleName;
        }

        private String getStarterVersion() {
            try {
                // 获取框架的版本号
                String starterVersion = GlobalConfig.class.getPackage().getImplementationVersion();
                if (StringUtils.isNotBlank(starterVersion)) {
                    return starterVersion;
                }
                // 读取版本号
                Resource resource = resourceLoader.getResource("classpath:StarterVersion");
                if (resource == null) {
                    return "unkown";
                }
                List lines = IOUtils.readLines(resource.getInputStream());
                if (lines != null && lines.size() > 0) {
                    return lines.get(0);
                }
            } catch (Exception e) {
                log.debug(ExceptionUtils.getStackTrace(e));
            }
            return "unkown";
        }
    }

    public void test() {
        File file = new File("/Users/liuchengbiao/devWork/sts-works/idea-work/gc-starter-work/gc-starter/gc-starter-server/pom.xml");
        System.out.println(new LicenseVerify().getModuleVersion(file));
        System.out.println(new LicenseVerify().getStarterVersion());
    }

    public static void main(String[] args) {
        new GlobalConfig().test();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy