czt
2025-01-11 83a5abea31bf14c78572d3a4c5fdf14afb97c82f
增加登录日志和错误次数校验
已添加10个文件
已修改6个文件
1242 ■■■■■ 文件已修改
src/main/java/com/fzzy/api/lic/AbstractServerInfos.java 143 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/fzzy/api/lic/LicenseCheckModel.java 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/fzzy/api/lic/LinuxServerInfos.java 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/fzzy/api/lic/WindowsServerInfos.java 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/fzzy/api/utils/SystemUtil.java 211 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/fzzy/push/gd2023/GD2023ApiRemoteService2023.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/fzzy/push/sx2024/SX2024ApiRemoteService.java 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/fzzy/sys/LogLogin.view.xml 169 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/fzzy/sys/LogLoginPR.java 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/fzzy/sys/LogLoginService.java 219 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/fzzy/sys/entity/LogLogin.java 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/fzzy/sys/repository/LogLoginRep.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/fzzy/web/LoginController.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-pro.yml 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application.yml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/templates/home/home.html 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/fzzy/api/lic/AbstractServerInfos.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,143 @@
package com.fzzy.api.lic;
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序列号、主板序列号等
 *
 * @author zifangsky
 * @date 2018/4/23
 * @since 1.0.0
 */
@Slf4j
public abstract class AbstractServerInfos {
    /**
     * ç»„装需要额外校验的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){
            log.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;
    }
}
src/main/java/com/fzzy/api/lic/LicenseCheckModel.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,77 @@
package com.fzzy.api.lic;
import java.io.Serializable;
import java.util.List;
/**
 * è‡ªå®šä¹‰éœ€è¦æ ¡éªŒçš„License参数
 *
 * @author zifangsky
 * @date 2018/4/23
 * @since 1.0.0
 */
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 + '\'' +
                '}';
    }
}
src/main/java/com/fzzy/api/lic/LinuxServerInfos.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,97 @@
package com.fzzy.api.lic;
import org.apache.commons.lang.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 readLine = reader.readLine();
        if(StringUtils.isNotEmpty(readLine)){
            String line = 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 readLine = reader.readLine();
        if(StringUtils.isNotEmpty(readLine)){
            String line = readLine.trim();
            if(StringUtils.isNotBlank(line)){
                serialNumber = line;
            }
        }
        reader.close();
        return serialNumber;
    }
}
src/main/java/com/fzzy/api/lic/WindowsServerInfos.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,89 @@
package com.fzzy.api.lic;
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;
    }
}
src/main/java/com/fzzy/api/utils/SystemUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,211 @@
package com.fzzy.api.utils;
import com.alibaba.fastjson.JSON;
import com.fzzy.api.lic.AbstractServerInfos;
import com.fzzy.api.lic.LicenseCheckModel;
import com.fzzy.api.lic.LinuxServerInfos;
import com.fzzy.api.lic.WindowsServerInfos;
import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.UnknownHostException;
import java.util.*;
/**
 * @Desc: èŽ·å–å®¢æˆ·ç™»é™†ä¿¡æ¯
 * @author: andy.jia
 * @update-time: 2022/11/10 19:55
 */
public class SystemUtil {
    /***
     * èŽ·å–å®¢æˆ·ç«¯IP地址
     * @param request
     */
    public static String getIP(HttpServletRequest request) {
        if (request == null) {
            return "127.0.0.1";
        }
        String ip = request.getHeader("X-Real-IP");
        if (ip != null && !"".equals(ip) && !"unknown".equalsIgnoreCase(ip)) {
            return ip;
        }
        ip = request.getHeader("X-Forwarded-For");
        if (ip != null && !"".equals(ip) && !"unknown".equalsIgnoreCase(ip)) {
            // å¤šæ¬¡åå‘代理后会有多个IP值,第一个为真实IP。
            int index = ip.indexOf(',');
            if (index != -1) {
                return ip.substring(0, index);
            } else {
                return ip;
            }
        } else {
            return request.getRemoteAddr();
        }
    }
    /**
     * èŽ·å–æ¥è®¿è€…çš„æµè§ˆå™¨ç‰ˆæœ¬
     *
     * @param request
     * @return
     */
    public static String getBrowserInfo(HttpServletRequest request) {
        String browserVersion = null;
        String header = request.getHeader("user-agent");
        if (header == null || header.equals("")) {
            return "";
        }
        if (header.indexOf("MSIE 6.0") > 0) {
            browserVersion = "IE 6";
        } else if (header.indexOf("MSIE 7.0") > 0) {
            browserVersion = "IE 7";
        } else if (header.indexOf("MSIE 8.0") > 0) {
            browserVersion = "IE 8";
        } else if (header.indexOf("MSIE 9.0") > 0) {
            browserVersion = "IE 9";
        } else if (header.indexOf("MSIE 10.0") > 0) {
            browserVersion = "IE 10";
        } else if (header.indexOf("rv:11.0") > 0) {
            browserVersion = "IE 11";
        } else if (header.indexOf("Firefox") > 0) {
            browserVersion = "Firefox";
        } else if (header.indexOf("Chrome") > 0) {
            browserVersion = "Chrome";
        } else if (header.indexOf("Safari") > 0) {
            browserVersion = "Safari";
        } else if (header.indexOf("Camino") > 0) {
            browserVersion = "Camino";
        } else if (header.indexOf("Konqueror") > 0) {
            browserVersion = "Konqueror";
        }
        return browserVersion;
    }
    /**
     * èŽ·å–ç³»ç»Ÿç‰ˆæœ¬ä¿¡æ¯
     *
     * @param request
     * @return
     */
    public static String getSystemInfo(HttpServletRequest request) {
        String systenInfo = null;
        String header = request.getHeader("user-agent");
        if (header == null || header.equals("")) {
            return "";
        }
        // å¾—到用户的操作系统
        if (header.indexOf("NT 6.0") > 0) {
            systenInfo = "Windows Vista/Server 2008";
        } else if (header.indexOf("NT 5.2") > 0) {
            systenInfo = "Windows Server 2003";
        } else if (header.indexOf("NT 5.1") > 0) {
            systenInfo = "Windows XP";
        } else if (header.indexOf("NT 6.0") > 0) {
            systenInfo = "Windows Vista";
        } else if (header.indexOf("NT 6.1") > 0) {
            systenInfo = "Windows 7";
        } else if (header.indexOf("NT 6.2") > 0) {
            systenInfo = "Windows Slate";
        } else if (header.indexOf("NT 6.3") > 0) {
            systenInfo = "Windows 9";
        } else if (header.indexOf("NT 10.0") > 0) {
            systenInfo = "Windows 10";
        } else if (header.indexOf("NT 5") > 0) {
            systenInfo = "Windows 2000";
        } else if (header.indexOf("NT 4") > 0) {
            systenInfo = "Windows NT4";
        } else if (header.indexOf("Me") > 0) {
            systenInfo = "Windows Me";
        }  else if (header.indexOf("Mac") > 0) {
            systenInfo = "Mac";
        } else if (header.indexOf("Unix") > 0) {
            systenInfo = "UNIX";
        } else if (header.indexOf("Linux") > 0) {
            systenInfo = "Linux";
        } else if (header.indexOf("SunOS") > 0) {
            systenInfo = "SunOS";
        }
        return systenInfo;
    }
    /**
     * èŽ·å–æ¥è®¿è€…çš„ä¸»æœºåç§°
     *
     * @param ip
     * @return
     */
    public static String getHostName(String ip) {
        InetAddress inet;
        try {
            inet = InetAddress.getByName(ip);
            return inet.getHostName();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        return "未知";
    }
    public static  String getSystemInfo() throws Exception {
        String os = System.getProperty("os.name").toLowerCase();
        Map<String ,Object> param =null;
        AbstractServerInfos abstractServerInfos = null;
        if (os.indexOf("win") >= 0) {
            param = new HashMap<>();
            abstractServerInfos = new WindowsServerInfos(); // Windows系统
            LicenseCheckModel data = abstractServerInfos.getServerInfos();
            //param.put("macAddress",data.getMacAddress());
            param.put("cpuSerial",data.getCpuSerial());
            param.put("mainBoardSerial",data.getMainBoardSerial());
        } else if (os.indexOf("mac") >= 0) {
            // Mac系统
        } else if (os.indexOf("nix") >= 0 || os.indexOf("nux") >= 0 || os.indexOf("aix") >= 0) {
            // Unix/Linux系统
            param = new HashMap<>();
            abstractServerInfos = new LinuxServerInfos();
            LicenseCheckModel data = abstractServerInfos.getServerInfos();
            //param.put("macAddress",data.getMacAddress())  ;
            param.put("cpuSerial",data.getCpuSerial())        ;
            param.put("mainBoardSerial",data.getMainBoardSerial());
        } else if (os.indexOf("sunos") >= 0) {
            // Solaris系统
        } else {
            // æœªçŸ¥çš„æ“ä½œç³»ç»Ÿ
        }
        if(null == param){
            return "";
        }else {
            return JSON.toJSONString(param);
        }
    }
    /**
     * èŽ·å–å½“å‰æœåŠ¡å™¨æ‰€æœ‰ç¬¦åˆæ¡ä»¶çš„InetAddress
     */
    protected static 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;
    }
}
src/main/java/com/fzzy/push/gd2023/GD2023ApiRemoteService2023.java
@@ -315,8 +315,7 @@
            BeanUtils.copyProperties(data, api1102);
            //校验统一编码是否为空,为空则查询库区信息进行赋值
            if (StringUtils.isEmpty(api1102.getTydwbm())) {
                String tydwbm = apiCommonService.getTydwbm(api1102.getDwdm());
                api1102.setTydwbm(tydwbm);
                api1102.setTydwbm(api1102.getTykqbm().substring(0, 20));
            }
            api1102.setZhgxsj(DateUtils.addSeconds(new Date(), -10));
            return JSON.toJSONString(api1102);
src/main/java/com/fzzy/push/sx2024/SX2024ApiRemoteService.java
@@ -100,14 +100,14 @@
            //获取指令id
            String key = RedisConst.buildKey(RedisConst.KYE_ORDER, conf.getKqdm());
            String orderId = (String) redisUtil.get(key);
            if (StringUtils.isEmpty(orderId)) {
                log.error("指令id失效");
                ResponseDto responseDto = new ResponseDto(99, "指令id失效");
                apiLog.setStatus(99);
                apiLog.setResult("指令id失效");
                apiLogRep.save(apiLog);
                return responseDto;
            }
//            if (StringUtils.isEmpty(orderId)) {
//                log.error("指令id失效");
//                ResponseDto responseDto = new ResponseDto(99, "指令id失效");
//                apiLog.setStatus(99);
//                apiLog.setResult("指令id失效");
//                apiLogRep.save(apiLog);
//                return responseDto;
//            }
            //封装推送数据
            SX2024ReqDto reqData = new SX2024ReqDto();
src/main/java/com/fzzy/sys/LogLogin.view.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,169 @@
<?xml version="1.0" encoding="UTF-8"?>
<ViewConfig>
  <Arguments/>
  <Context/>
  <Model>
    <DataType name="dtMain">
      <Property name="creationType">com.fzzy.sys.entity.LogLogin</Property>
      <PropertyDef name="id">
        <Property></Property>
        <Property name="label">ID</Property>
      </PropertyDef>
      <PropertyDef name="companyId">
        <Property></Property>
        <Property name="label">组织编码</Property>
      </PropertyDef>
      <PropertyDef name="loginId">
        <Property></Property>
        <Property name="label">登陆ID</Property>
      </PropertyDef>
      <PropertyDef name="loginName">
        <Property></Property>
        <Property name="label">登陆用户</Property>
      </PropertyDef>
      <PropertyDef name="loginTime">
        <Property name="dataType">DateTime</Property>
        <Property name="label">登陆时间</Property>
      </PropertyDef>
      <PropertyDef name="errorNum">
        <Property name="dataType">Integer</Property>
        <Property name="label">错误次数</Property>
        <Property name="displayFormat">#0 æ¬¡</Property>
      </PropertyDef>
      <PropertyDef name="ip">
        <Property name="label">登陆者IP</Property>
      </PropertyDef>
      <PropertyDef name="browser">
        <Property name="label">浏览器</Property>
      </PropertyDef>
      <PropertyDef name="sysName">
        <Property name="label">操作系统</Property>
      </PropertyDef>
      <PropertyDef name="hostName">
        <Property name="label">登陆主机</Property>
      </PropertyDef>
      <PropertyDef name="netInfo">
        <Property name="label">网络状况</Property>
      </PropertyDef>
      <PropertyDef name="lastLoginTime">
        <Property name="dataType">Date</Property>
        <Property name="label">上次登陆时间</Property>
      </PropertyDef>
      <PropertyDef name="loginInfo">
        <Property name="label">登陆说明</Property>
      </PropertyDef>
    </DataType>
    <DataType name="dtParam">
      <PropertyDef name="start">
        <Property name="dataType">Date</Property>
        <Property name="label">开始日期</Property>
      </PropertyDef>
      <PropertyDef name="end">
        <Property name="dataType">Date</Property>
        <Property name="label">截止日期</Property>
      </PropertyDef>
    </DataType>
  </Model>
  <View layout="regionPadding:10">
    <ClientEvent name="onReady">view.get(&quot;#dsParam&quot;).insert({});</ClientEvent>
    <Property name="packages">font-awesome,css-common</Property>
    <DataSet id="dsMain">
      <Property name="dataProvider">logLoginPR#pageLogLogin</Property>
      <Property name="dataType">[dtMain]</Property>
      <Property name="pageSize">15</Property>
    </DataSet>
    <DataSet id="dsParam">
      <Property name="dataType">dtParam</Property>
    </DataSet>
    <Container layout="regionPadding:10" layoutConstraint="center">
      <Property name="exClassName">bg-color</Property>
      <AutoForm>
        <Property name="dataSet">dsParam</Property>
        <Property name="cols">*,*,*,*</Property>
        <AutoFormElement>
          <Property name="name">start</Property>
          <Property name="property">start</Property>
          <Editor/>
        </AutoFormElement>
        <AutoFormElement>
          <Property name="name">end</Property>
          <Property name="property">end</Property>
          <Editor/>
        </AutoFormElement>
        <Container layout="regionPadding:10">
          <Button layoutConstraint="left">
            <ClientEvent name="onClick">var param = view.get(&quot;#dsParam.data&quot;);&#xD;
view.get(&quot;#dsMain&quot;).set(&quot;parameter&quot;,param).flushAsync();</ClientEvent>
            <Property name="caption">查询</Property>
            <Property name="exClassName">btn-normal</Property>
            <Property name="iconClass">fa fa-search</Property>
          </Button>
          <Button layoutConstraint="left">
            <ClientEvent name="onClick">view.get(&quot;#dsParam&quot;).flushAsync();</ClientEvent>
            <Property name="caption">重置</Property>
            <Property name="iconClass">fa fa-refresh</Property>
            <Property name="exClassName">btn-default</Property>
          </Button>
        </Container>
      </AutoForm>
      <DataGrid id="dgMain">
        <ClientEvent name="onDataRowDoubleClick">var dialog= view.get(&quot;#dialogMain&quot;);&#xD;
dialog.show();</ClientEvent>
        <Property name="dataSet">dsMain</Property>
        <Property name="readOnly">true</Property>
        <RowNumColumn/>
        <DataColumn name="loginName">
          <Property name="property">loginName</Property>
          <Property name="align">center</Property>
        </DataColumn>
        <DataColumn name="loginId">
          <Property name="property">loginId</Property>
          <Property name="align">center</Property>
        </DataColumn>
        <DataColumn name="loginTime">
          <Property name="property">loginTime</Property>
          <Property name="align">center</Property>
        </DataColumn>
        <DataColumn name="errorNum">
          <Property name="property">errorNum</Property>
          <Property name="align">center</Property>
        </DataColumn>
        <DataColumn name="ip">
          <Property name="property">ip</Property>
          <Property name="align">center</Property>
        </DataColumn>
        <DataColumn name="browser">
          <Property name="property">browser</Property>
          <Property name="align">center</Property>
        </DataColumn>
        <DataColumn name="sysName">
          <Property name="property">sysName</Property>
          <Property name="align">center</Property>
        </DataColumn>
        <DataColumn name="hostName">
          <Property name="property">hostName</Property>
          <Property name="align">center</Property>
        </DataColumn>
        <DataColumn name="netInfo">
          <Property name="property">netInfo</Property>
          <Property name="align">center</Property>
        </DataColumn>
        <DataColumn name="loginInfo">
          <Property name="property">loginInfo</Property>
          <Property name="align">center</Property>
        </DataColumn>
        <DataColumn name="lastLoginTime">
          <Property name="property">lastLoginTime</Property>
          <Property name="align">center</Property>
        </DataColumn>
      </DataGrid>
    </Container>
    <Container layoutConstraint="bottom">
      <Property name="exClassName">bg-color</Property>
      <DataPilot layoutConstraint="right">
        <Property name="dataSet">dsMain</Property>
        <Property name="itemCodes">pageSize,pages</Property>
      </DataPilot>
    </Container>
  </View>
</ViewConfig>
src/main/java/com/fzzy/sys/LogLoginPR.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,78 @@
package com.fzzy.sys;
import com.bstek.dorado.annotation.DataProvider;
import com.fzzy.sys.entity.LogLogin;
import com.fzzy.api.utils.ContextUtil;
import com.fzzy.sys.repository.LogLoginRep;
import org.springframework.beans.factory.annotation.Autowired;
import com.bstek.dorado.data.provider.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
 * @Description ç™»å½•日志
 * @Author CZT
 * @Date 2024/5/30 15:53
 */
@Component
public class LogLoginPR {
    @Autowired
    private LogLoginRep logLoginRep;
    /**
     * logLoginPR#pageLogLogin
     *
     * @param page
     * @param param
     * @throws Exception
     */
    @DataProvider
    public void pageLogLogin(Page<LogLogin> page, Map<String, Object> param) {
        //多参数分页查询
        Pageable pageable = PageRequest.of(page.getPageNo() - 1, page.getPageSize(), Sort.Direction.DESC, LogLogin.SORT_PROP);
        if (null == param) {
            org.springframework.data.domain.Page<LogLogin> japPage = logLoginRep.findAll(pageable);
            page.setEntityCount((int) japPage.getTotalElements());
            page.setEntities(japPage.getContent());
            return;
        }
        Specification<LogLogin> specification = new Specification<LogLogin>() {
            private static final long serialVersionUID = 1L;
            public Predicate toPredicate(Root<LogLogin> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> predicates = new ArrayList<>(); //所有的断言
                Date date = (Date) param.get("start");
                if (null != date) {
                    Predicate predicate3 = cb.greaterThan(root.get("loginTime"), ContextUtil.getCurZero(date));
                    predicates.add(predicate3);
                }
                date = (Date) param.get("end");
                if (null != date) {
                    Predicate predicate4 = cb.lessThan(root.get("loginTime"), ContextUtil.getNextZero(date));
                    predicates.add(predicate4);
                }
                return cb.and(predicates.toArray(new Predicate[0]));
            }
        };
        org.springframework.data.domain.Page<LogLogin> japPage = logLoginRep.findAll(specification, pageable);
        page.setEntityCount((int) japPage.getTotalElements());
        page.setEntities(japPage.getContent());
    }
}
src/main/java/com/fzzy/sys/LogLoginService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,219 @@
package com.fzzy.sys;
import com.fzzy.api.utils.ContextUtil;
import com.fzzy.sys.entity.LogLogin;
import com.fzzy.api.utils.RedisConst;
import com.fzzy.api.utils.RedisUtil;
import com.fzzy.api.utils.SystemUtil;
import com.fzzy.sys.repository.LogLoginRep;
import com.fzzy.sys.entity.SysUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
/**
 * @Desc: ç™»é™†æ—¥å¿—记录信息
 * @author: andy.jia
 * @update-time: 2023/4/28 8:32
 */
@Component
public class LogLoginService{
    private String KEY_LOGON_LOG = "LOGIN_LOG";
    private int TIME_ERROR_MIN = 60;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private LogLoginRep logLoginRep;
    /**
     * åˆ¤æ–­å½“前登陆是否被限制
     *
     * @param request
     * @param username
     * @return
     */
    public int checkLoginLimit(HttpServletRequest request, String username) {
        //获取错误记录缓存
        LogLogin errorLog = this.getFromCacheError(username, SystemUtil.getIP(request));
        if (null == errorLog) return 0;
        return errorLog.getErrorNum();
    }
    /**
     * å¯†ç è¾“入错误记录,返回输入错误次数
     *
     * @param request
     * @param user
     * @return
     */
    public int addPwdError(HttpServletRequest request, SysUser user) {
        LogLogin log = new LogLogin();
        log.setCompanyId(user.getCompanyId());
        log.setLoginId(user.getUsername());
        log.setLoginName(user.getName());
        log.setLoginTime(new Date());
        log.setIp(SystemUtil.getIP(request));
        log.setBrowser(SystemUtil.getBrowserInfo(request));
        log.setSysName(SystemUtil.getSystemInfo(request));
        log.setHostName(SystemUtil.getHostName(log.getIp()));
        log.setLastLoginTime(new Date());
        log.setErrorNum(1);
        log.setLoginInfo("失败:密码错误");
        // èŽ·å–ä¸Šæ¬¡é”™è¯¯è®°å½•
        LogLogin errorLog = this.getFromCacheError(user.getUsername(), log.getIp());
        if (null != errorLog) {
            log.setErrorNum(errorLog.getErrorNum() + 1);
        }
        //保存日志
        addLog(log);
        //保存到缓存
        addToCacheError(log);
        return log.getErrorNum();
    }
    /**
     * ç™»é™†ç”¨æˆ·ä¸å­˜åœ¨é”™è¯¯ï¼Œè¿”回输入不存在账号次数,用户不存在的账号,使用IP作为判断标准,避免恶意尝试
     *
     * @param request
     * @param username
     * @return
     */
    public int addNoUser(HttpServletRequest request, String username) {
        LogLogin log = new LogLogin();
        log.setLoginName(username);
        log.setLoginTime(new Date());
        log.setIp(SystemUtil.getIP(request));
        log.setBrowser(SystemUtil.getBrowserInfo(request));
        log.setSysName(SystemUtil.getSystemInfo(request));
        log.setHostName(SystemUtil.getHostName(log.getIp()));
        log.setLastLoginTime(new Date());
        log.setErrorNum(1);
        log.setLoginId(log.getIp());
        log.setLoginInfo("失败:无效账号");
        // èŽ·å–ä¸Šæ¬¡é”™è¯¯è®°å½•
        LogLogin errorLog = this.getFromCacheError(log.getIp(), log.getIp());
        if (null != errorLog) {
            log.setErrorNum(errorLog.getErrorNum() + 1);
        }
        //保存到缓存
        addToCache(log);
        //保存日志
        log.setLoginId(username);
        addLog(log);
        return log.getErrorNum();
    }
    /**
     * å¢žåŠ ç™»é™†æ—¥å¿—ä¿¡æ¯
     *
     * @param request
     * @param user
     */
    public void addLoginInfo(HttpServletRequest request, SysUser user) {
        LogLogin log = new LogLogin();
        log.setCompanyId(user.getCompanyId());
        log.setLoginId(user.getUsername());
        log.setLoginName(user.getName());
        log.setLoginTime(new Date());
        log.setIp(SystemUtil.getIP(request));
        log.setBrowser(SystemUtil.getBrowserInfo(request));
        log.setSysName(SystemUtil.getSystemInfo(request));
        log.setHostName(SystemUtil.getHostName(log.getIp()));
        log.setErrorNum(0);
        log.setLoginInfo("成功:正常登陆");
        // èŽ·å–ä¸Šæ¬¡ç™»é™†ä¿¡æ¯
        LogLogin lastLog = this.getFromCache(log.getLoginId());
        if (null != lastLog) {
            log.setLastLoginTime(lastLog.getLoginTime());
        }
        //保存缓存
        addToCache(log);
        //保存日志
        addLog(log);
    }
    /**
     * @param log
     */
    private void addToCache(LogLogin log) {
        String key = RedisConst.buildKey(KEY_LOGON_LOG, log.getLoginId());
        redisUtil.set(key, log);
        this.removeCacheError(log.getLoginId(), log.getIp());
    }
    private LogLogin getFromCache(String loginId) {
        if (null == loginId) return null;
        try {
            String key = RedisConst.buildKey(KEY_LOGON_LOG, loginId);
            return (LogLogin) redisUtil.get(key);
        } catch (Exception e) {
            return null;
        }
    }
    private void removeCacheError(String loginId, String ip) {
        String key = RedisConst.buildKey(KEY_LOGON_LOG, loginId, ip);
        redisUtil.del(key);
    }
    private void addToCacheError(LogLogin log) {
        String key = RedisConst.buildKey(KEY_LOGON_LOG, log.getLoginId(), log.getIp());
        redisUtil.set(key, log, (TIME_ERROR_MIN + 1) * 60);
    }
    private LogLogin getFromCacheError(String loginId, String ip) {
        if (null == loginId) return null;
        if (null == ip) return null;
        try {
            String key = RedisConst.buildKey(KEY_LOGON_LOG, loginId, ip);
            return (LogLogin) redisUtil.get(key);
        } catch (Exception e) {
            return null;
        }
    }
    /**
     * @Desc: ä¿å­˜æ—¥å¿—
     * @author: Andy
     * @update-time: 2023/4/28
     */
    public void addLog(LogLogin log) {
        if (null == log) return;
        if (null == log.getId()) {
            log.setId(ContextUtil.getUUID());
        }
        logLoginRep.save(log);
    }
}
src/main/java/com/fzzy/sys/entity/LogLogin.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,78 @@
package com.fzzy.sys.entity;
import com.bstek.dorado.annotation.PropertyDef;
import lombok.Data;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;
import java.util.Date;
/**
 * @Desc: ç³»ç»Ÿç™»é™†æ—¥å¿—
 * @author: Andy
 * @update-time: 2023/4/27
 */
@Data
@Entity
@Table(name = "D_LOG_LOGIN")
public class LogLogin implements Serializable {
    public static String SORT_PROP = "id";
    @Id
    @Column(name = "ID_", unique = true, length = 40)
    @PropertyDef(label = "ID")
    private String id;
    @Column(name = "COMPANY_ID", length = 10)
    @PropertyDef(label = "组织编码")
    private String companyId;
    @Column(name = "LOGIN_ID", length = 40)
    @PropertyDef(label = "登陆ID")
    private String loginId;
    @Column(name = "LOGIN_NAME", length = 40)
    @PropertyDef(label = "登陆用户")
    private String loginName;
    @Column(name = "LOGIN_TIME")
    @PropertyDef(label = "登陆时间")
    private Date loginTime;
    @Column(name = "ERROR_NUM")
    @PropertyDef(label = "错误次数")
    private int errorNum;
    @Column(name = "IP_", length = 20)
    @PropertyDef(label = "登陆者IP")
    private String ip;
    @Column(name = "BROSWER_", length = 50)
    @PropertyDef(label = "浏览器")
    private String browser;
    @Column(name = "SYS_NAME", length = 50)
    @PropertyDef(label = "操作系统")
    private String sysName;
    @Column(name = "HOST_NAME", length = 50)
    @PropertyDef(label = "登陆主机")
    private String hostName;
    @Column(name = "NET_INFO", length = 50)
    @PropertyDef(label = "网络状况")
    private String netInfo = "正常";
    @Column(name = "LAST_LOGIN_TIME")
    @PropertyDef(label = "上次登陆时间")
    private Date lastLoginTime;
    @Column(name = "LOGIN_INFO")
    @PropertyDef(label = "登陆说明")
    private String loginInfo;
}
src/main/java/com/fzzy/sys/repository/LogLoginRep.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,9 @@
package com.fzzy.sys.repository;
import com.fzzy.sys.entity.LogLogin;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface LogLoginRep extends JpaRepository<LogLogin, String>, JpaSpecificationExecutor<LogLogin> {
}
src/main/java/com/fzzy/web/LoginController.java
@@ -1,5 +1,6 @@
package com.fzzy.web;
import com.fzzy.sys.LogLoginService;
import com.fzzy.sys.UserPR;
import com.fzzy.sys.entity.SysUser;
import com.wf.captcha.ArithmeticCaptcha;
@@ -26,6 +27,8 @@
    @Autowired
    private UserPR userPR;
    @Autowired
    private LogLoginService logLoginService;
    /**
     * ç™»å½•验证入口
@@ -54,16 +57,32 @@
            return "redirect:/login?tag=04&username=" + username;
        }
        //判断限制登陆
        int num = logLoginService.checkLoginLimit(request, username);
        if (num >= 3) {
            return "redirect:/login?tag=11&username=" + username;
        }
        SysUser user = userPR.listById(username);
        if (null == user) {
            num = logLoginService.addNoUser(request, username);
            if (num >= 3) {
                return "redirect:/login?tag=12&username=" + username;
            }
            return "redirect:/login?tag=05&username=" + username;
        }
        boolean tag = userPR.checkPassword(password, user);
        if (!tag){
            num = logLoginService.addPwdError(request, user);
            if (num >= 3) {
                return "redirect:/login?tag=11&username=" + username;
            }
            return "redirect:/login?tag=06&username=" + username;
        }
        request.getSession().setAttribute("user", user);
        //增加登录日志
        logLoginService.addLoginInfo(request, user);
        return "redirect:/home";
    }
@@ -103,6 +122,12 @@
            if ("10".equals(tag)) {
                tag = "您的账号在其他地方登录,被迫下线";
            }
            if ("11".equals(tag)) {
                tag = "连续3次错误,限制登陆60分钟";
            }
            if ("12".equals(tag)) {
                tag = "连续3次输入不存在账号,限制登陆60分钟";
            }
            view.addObject("TAG", tag);
            view.addObject("USERNAME", username);
        }
src/main/resources/application-pro.yml
@@ -1,6 +1,6 @@
##########################  å®å¤çŸ³å˜´å±±çº¢æžœå­ç²®åº“   ##########################
##########################  é™•西柞水县   ##########################
server:
  port: 8090
  port: 8091
  jetty:
    max-http-post-size: 209715200
  tomcat:
@@ -9,16 +9,16 @@
  datasource:
    #主数据源
    primary:
      url: jdbc:mysql://127.0.0.1:3306/igds_api?useUnicode=true&characterEncoding=utf-8
      url: jdbc:mysql://127.0.0.1:3306/igds_api_2024?useUnicode=true&characterEncoding=utf-8&useSSL=false
      driver-class-name: com.mysql.jdbc.Driver
      username: root
      password: Abc123..
      password: Fzzy@#$%5432..K
    #次数据源
    secondary:
      url: jdbc:mysql://127.0.0.1:3306/igds_master?useUnicode=true&characterEncoding=utf-8
      url: jdbc:mysql://127.0.0.1:3306/igds_master?useUnicode=true&characterEncoding=utf-8&useSSL=false
      driver-class-name: com.mysql.jdbc.Driver
      username: root
      password: Abc123..
      password: Fzzy@#$%5432..K
  jpa:
    #主jpa配置
    primary:
@@ -41,7 +41,7 @@
    database: 1
    host: 127.0.0.1
    port: 6379
    password: Abc123..
    password: Redispwd..
    # è¿žæŽ¥æ± æœ€å¤§è¿žæŽ¥æ•°ï¼ˆä½¿ç”¨è´Ÿå€¼è¡¨ç¤ºæ²¡æœ‰é™åˆ¶ï¼‰
    pool:
      max-active: 200
@@ -51,11 +51,6 @@
      timeout: 6000
igds:
  default:
    companyId: 5306
    companyId: 5348
  file-path: D:/IGDS-API/FILE/
  img-path: D:/IGDS/FILE/
  # çœå¹³å°RSA密钥对信息
  #公钥:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCsoiS5Q5CKAT9w5EbZXCxJO/5J2iV3i2HrTW/YcGs2EGeQsQc97EWPdFE1SPXGH5p9TO8nCFRJScj4WeeKUVcuRpzR7czQQ+c6kf6cR9LLQrAiGEMQSk13j/5UsJho23IQDGKWoH18f5aPdX8tJn/o4aR6mMxUY9jdaSKEBck1TQIDAQAB
  # åŒºçº§å¹³å°RSA密钥对信息
  #公钥:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCMsCJyl6EkjUEfB9Otl0bNmFD0Gr3g/v8DYnoq66EIviDNKT+bo5Aj6BRFngns1aCy1uyWgC5/+PIQ3sxs25nWXxFBYXy7cTiGwCCPfnmmI3rkXRGqRo6uh9K3BsucSE0kyhB8Eq76bQ6BPa5XpMyyq8V2oN2i0LLYpDhV97j3BwIDAQAB
  #私钥:MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIywInKXoSSNQR8H062XRs2YUPQaveD+/wNieirroQi+IM0pP5ujkCPoFEWeCezVoLLW7JaALn/48hDezGzbmdZfEUFhfLtxOIbAII9+eaYjeuRdEapGjq6H0rcGy5xITSTKEHwSrvptDoE9rlekzLKrxXag3aLQstikOFX3uPcHAgMBAAECgYAOZvWPz4/ygvdYqt9zlNntsBsRci9f+hq3CPzCqg55K6WF+yQE1dCqrFZu7gfME+54gGIF4idgeGanbXd16WEtFslEJlFKGk3cF62gaX5Y/nZ4zS65CLTjQ650j6SJ7OC2QYjIejTWhJD0k1tSazXdzV70nP+X3DbGyyO3Rm+juQJBANMCi+9RnzcGvltN/AdWD0DgshRBNrqrHtDkmzRFSkFwIqVSL5J7qRvntjhSstQIBB5KCosCmwRYKxGWQ9Ou420CQQCqrz2byBz3w2pkEfPY3rv7T4zE/2CHC74XtW9sEUTieYaxqIKlnwJacactzx4ZOAg21dGCoqOG9Y9RIpH2mMfDAkEAlAucXIt61qOfmPXtFsSVrSI5LybWHEAFPfC2yAS5ZZIkbLNt9ytV6eM3oOq81zDMmue93+wzEOg/R3aTHgj9PQJALNGxUsu8V473y+ku596s6/PamgwZE70QoHcjF/R86x9QMCx4ifb0Dj3T0WKWm7ar6YJB7pS4bgLjLEHwpBlAMwJAUUG2NhfGXFxfyFOC+5BzFTEr7EdSeHPXJl7dIWmRHncHsv8Nl2yvWsIOfDOYKS3ynptMgeSZaJPnXhvFdX0TnQ==
  img-path: D:/IGDS/FILE/
src/main/resources/application.yml
@@ -1,7 +1,7 @@
##########################  Server   ##########################
spring:
  profiles:
    active: pro
    active: dev
  application:
    name: igds-api
  main:
src/main/resources/templates/home/home.html
@@ -101,6 +101,9 @@
                            <dd>
                                <a lay-href="com.fzzy.api.view.GbUnifiedCoding.d">统一编码管理</a>
                            </dd>
                            <dd>
                                <a lay-href="com.fzzy.sys.LogLogin.d">登录日志</a>
                            </dd>
                        </dl>
                    </li>