coder-common-thin-backend/api/system/登录日志API.md
Leo aea2b1fbd7 docs: 新增完整的API接口文档
- 添加认证相关API文档(登录认证、验证码)
- 添加权限管理API文档(菜单管理、角色管理)
- 添加系统管理API文档(图片管理、文件管理、登录日志)
- 添加用户管理API文档
- 完善项目API文档结构,提升开发体验
2025-07-06 00:54:47 +08:00

27 KiB
Raw Blame History

登录日志API

概述

登录日志模块用于记录和管理系统用户的登录行为,包括登录成功、登录失败、退出登录等操作的详细记录。提供日志查询、统计分析和安全监控功能,是系统安全审计的重要组成部分。

权限说明

登录日志接口需要相应的权限才能访问:

操作 权限码 说明
查询登录日志 system:loginlog:list 查看登录日志权限
删除登录日志 system:loginlog:remove 删除登录日志权限
导出登录日志 system:loginlog:export 导出登录日志权限

接口列表

1. 分页查询登录日志

接口地址: GET /coder/sysLoginLog/listPage

接口描述: 分页查询系统登录日志列表

是否需要认证: 是

权限要求: system:loginlog:list

请求头:

Authorization: Bearer your-token-value

请求参数:

参数名 类型 必填 说明 示例
pageNo Integer 页码 1
pageSize Integer 每页大小 10
loginName String 登录账号 admin
loginStatus String 登录状态 0
clientType String 客户端类型 WEB
loginIp String 登录IP 127.0.0.1
loginAddress String 登录地址 本地登录
browser String 浏览器类型 Chrome
os String 操作系统 Windows 10
beginTime String 开始时间 2024-01-01
endTime String 结束时间 2024-12-31

响应示例:

{
  "status": 200,
  "msg": "SUCCESS",
  "data": {
    "records": [
      {
        "infoId": 1,
        "loginName": "admin",
        "userName": "管理员",
        "userId": 1,
        "loginStatus": "0",
        "clientType": "WEB",
        "deviceName": "Windows PC",
        "loginIp": "127.0.0.1",
        "loginAddress": "本地登录",
        "browser": "Chrome 120.0.0.0",
        "os": "Windows 10",
        "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
        "loginTime": "2024-07-05 10:00:00",
        "logoutTime": "2024-07-05 11:00:00",
        "sessionDuration": 3600,
        "failureReason": "",
        "remark": "登录成功",
        "createBy": "system",
        "createTime": "2024-07-05 10:00:00",
        "updateBy": "system",
        "updateTime": "2024-07-05 11:00:00"
      }
    ],
    "total": 1,
    "size": 10,
    "current": 1,
    "pages": 1
  },
  "traceId": "trace-123456"
}

调用示例:

curl -X GET \
  "http://localhost:18099/coder/sysLoginLog/listPage?pageNo=1&pageSize=10&loginName=admin&loginStatus=0" \
  -H "Authorization: Bearer your-token-value"

2. 查询所有登录日志

接口地址: GET /coder/sysLoginLog/list

接口描述: 查询所有系统登录日志(不分页)

是否需要认证: 是

权限要求: system:loginlog:list

请求参数: 同分页查询除pageNo、pageSize外

响应示例:

{
  "status": 200,
  "msg": "SUCCESS",
  "data": [
    {
      "infoId": 1,
      "loginName": "admin",
      "userName": "管理员",
      "userId": 1,
      "loginStatus": "0",
      "clientType": "WEB",
      "deviceName": "Windows PC",
      "loginIp": "127.0.0.1",
      "loginAddress": "本地登录",
      "browser": "Chrome 120.0.0.0",
      "os": "Windows 10",
      "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
      "loginTime": "2024-07-05 10:00:00",
      "logoutTime": "2024-07-05 11:00:00",
      "sessionDuration": 3600,
      "failureReason": "",
      "remark": "登录成功",
      "createBy": "system",
      "createTime": "2024-07-05 10:00:00",
      "updateBy": "system",
      "updateTime": "2024-07-05 11:00:00"
    }
  ],
  "traceId": "trace-123456"
}

调用示例:

curl -X GET \
  "http://localhost:18099/coder/sysLoginLog/list?loginStatus=1&beginTime=2024-07-01" \
  -H "Authorization: Bearer your-token-value"

3. 根据ID查询登录日志

接口地址: GET /coder/sysLoginLog/getById/{id}

接口描述: 根据日志ID查询登录日志详细信息

是否需要认证: 是

权限要求: system:loginlog:list

路径参数:

参数名 类型 必填 说明
id Long 日志ID

响应示例:

{
  "status": 200,
  "msg": "SUCCESS",
  "data": {
    "infoId": 1,
    "loginName": "admin",
    "userName": "管理员",
    "userId": 1,
    "loginStatus": "0",
    "clientType": "WEB",
    "deviceName": "Windows PC",
    "loginIp": "127.0.0.1",
    "loginAddress": "本地登录",
    "browser": "Chrome 120.0.0.0",
    "os": "Windows 10",
    "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
    "loginTime": "2024-07-05 10:00:00",
    "logoutTime": "2024-07-05 11:00:00",
    "sessionDuration": 3600,
    "failureReason": "",
    "remark": "登录成功",
    "createBy": "system",
    "createTime": "2024-07-05 10:00:00",
    "updateBy": "system",
    "updateTime": "2024-07-05 11:00:00"
  },
  "traceId": "trace-123456"
}

调用示例:

curl -X GET \
  http://localhost:18099/coder/sysLoginLog/getById/1 \
  -H "Authorization: Bearer your-token-value"

4. 新增登录日志

接口地址: POST /coder/sysLoginLog/add

接口描述: 新增系统登录日志记录

是否需要认证: 是

权限要求: system:loginlog:add

请求参数:

{
  "loginName": "admin",
  "userName": "管理员",
  "userId": 1,
  "loginStatus": "0",
  "clientType": "WEB",
  "deviceName": "Windows PC",
  "loginIp": "127.0.0.1",
  "loginAddress": "本地登录",
  "browser": "Chrome 120.0.0.0",
  "os": "Windows 10",
  "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
  "loginTime": "2024-07-05 10:00:00",
  "failureReason": "",
  "remark": "登录成功"
}

请求参数说明:

参数名 类型 必填 说明 校验规则
loginName String 登录账号 不能为空
userName String 用户姓名 可为空
userId Long 用户ID 有效的用户ID
loginStatus String 登录状态 0-成功 1-失败
clientType String 客户端类型 WEB, MOBILE, API
deviceName String 设备名称 可为空
loginIp String 登录IP 有效的IP地址
loginAddress String 登录地址 可为空
browser String 浏览器信息 可为空
os String 操作系统 可为空
userAgent String 用户代理 可为空
loginTime String 登录时间 时间格式
failureReason String 失败原因 登录失败时必填
remark String 备注信息 最长500字符

响应示例:

{
  "status": 200,
  "msg": "SUCCESS",
  "data": "新增成功",
  "traceId": "trace-123456"
}

调用示例:

curl -X POST \
  http://localhost:18099/coder/sysLoginLog/add \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-token-value" \
  -d '{
    "loginName": "admin",
    "userName": "管理员",
    "userId": 1,
    "loginStatus": "0",
    "clientType": "WEB",
    "loginIp": "127.0.0.1",
    "loginTime": "2024-07-05 10:00:00",
    "remark": "登录成功"
  }'

5. 修改登录日志

接口地址: POST /coder/sysLoginLog/update

接口描述: 修改系统登录日志信息(通常用于更新退出时间)

是否需要认证: 是

权限要求: system:loginlog:edit

请求参数:

{
  "infoId": 1,
  "loginName": "admin",
  "userName": "管理员",
  "userId": 1,
  "loginStatus": "0",
  "clientType": "WEB",
  "deviceName": "Windows PC",
  "loginIp": "127.0.0.1",
  "loginAddress": "本地登录",
  "browser": "Chrome 120.0.0.0",
  "os": "Windows 10",
  "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
  "loginTime": "2024-07-05 10:00:00",
  "logoutTime": "2024-07-05 11:00:00",
  "sessionDuration": 3600,
  "failureReason": "",
  "remark": "正常退出"
}

请求参数说明:

参数名 类型 必填 说明 校验规则
infoId Long 日志ID 必须是有效的日志ID
logoutTime String 退出时间 时间格式
sessionDuration Integer 会话时长(秒) 大于等于0
其他参数 - - 同新增日志 -

响应示例:

{
  "status": 200,
  "msg": "SUCCESS",
  "data": "修改成功",
  "traceId": "trace-123456"
}

调用示例:

curl -X POST \
  http://localhost:18099/coder/sysLoginLog/update \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-token-value" \
  -d '{
    "infoId": 1,
    "logoutTime": "2024-07-05 11:00:00",
    "sessionDuration": 3600,
    "remark": "正常退出"
  }'

6. 删除登录日志

接口地址: POST /coder/sysLoginLog/deleteById/{id}

接口描述: 根据ID删除登录日志

是否需要认证: 是

权限要求: system:loginlog:remove

路径参数:

参数名 类型 必填 说明
id Long 日志ID

响应示例:

{
  "status": 200,
  "msg": "SUCCESS",
  "data": "删除成功",
  "traceId": "trace-123456"
}

调用示例:

curl -X POST \
  http://localhost:18099/coder/sysLoginLog/deleteById/1 \
  -H "Authorization: Bearer your-token-value"

7. 批量删除登录日志

接口地址: POST /coder/sysLoginLog/batchDelete

接口描述: 批量删除登录日志

是否需要认证: 是

权限要求: system:loginlog:remove

请求参数:

{
  "ids": [1, 2, 3]
}

请求参数说明:

参数名 类型 必填 说明
ids Long[] 日志ID数组

响应示例:

{
  "status": 200,
  "msg": "SUCCESS",
  "data": "删除成功",
  "traceId": "trace-123456"
}

调用示例:

curl -X POST \
  http://localhost:18099/coder/sysLoginLog/batchDelete \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-token-value" \
  -d '{
    "ids": [1, 2, 3]
  }'

登录日志字段说明

基础字段

字段名 类型 说明 示例
infoId Long 日志ID 1
loginName String 登录账号 admin
userName String 用户姓名 管理员
userId Long 用户ID 1

状态字段

字段名 类型 说明 示例
loginStatus String 登录状态 0-成功 1-失败
clientType String 客户端类型 WEB, MOBILE, API
deviceName String 设备名称 Windows PC

网络字段

字段名 类型 说明 示例
loginIp String 登录IP地址 127.0.0.1
loginAddress String 登录地理位置 本地登录
userAgent String 用户代理字符串 Mozilla/5.0...

环境字段

字段名 类型 说明 示例
browser String 浏览器信息 Chrome 120.0.0.0
os String 操作系统 Windows 10

时间字段

字段名 类型 说明 示例
loginTime String 登录时间 2024-07-05 10:00:00
logoutTime String 退出时间 2024-07-05 11:00:00
sessionDuration Integer 会话时长(秒) 3600

其他字段

字段名 类型 说明 示例
failureReason String 失败原因 密码错误
remark String 备注信息 登录成功

数据字典

登录状态 (loginStatus)

说明
0 登录成功
1 登录失败

客户端类型 (clientType)

说明
WEB 网页端
MOBILE 移动端
API 接口调用
DESKTOP 桌面应用
WECHAT 微信小程序

常见失败原因

失败原因 说明
用户不存在 登录账号不存在
密码错误 登录密码不正确
验证码错误 验证码输入错误
账号被禁用 用户账号被禁用
账号被锁定 用户账号被锁定
IP被限制 登录IP被限制
设备被限制 登录设备被限制
会话过期 用户会话已过期

日志记录机制

1. 自动记录

@Component
@Slf4j
public class LoginLogService {
    
    /**
     * 记录登录成功日志
     */
    public void recordLoginSuccess(String loginName, HttpServletRequest request) {
        try {
            SysLoginLog loginLog = new SysLoginLog();
            
            // 基础信息
            loginLog.setLoginName(loginName);
            loginLog.setUserId(getCurrentUserId(loginName));
            loginLog.setUserName(getCurrentUserName(loginName));
            loginLog.setLoginStatus("0");
            loginLog.setLoginTime(LocalDateTime.now());
            
            // 网络信息
            loginLog.setLoginIp(getClientIP(request));
            loginLog.setLoginAddress(getAddressByIP(loginLog.getLoginIp()));
            
            // 客户端信息
            loginLog.setClientType(getClientType(request));
            loginLog.setUserAgent(request.getHeader("User-Agent"));
            loginLog.setBrowser(getBrowserInfo(request));
            loginLog.setOs(getOSInfo(request));
            loginLog.setDeviceName(getDeviceName(request));
            
            // 其他信息
            loginLog.setRemark("登录成功");
            loginLog.setCreateBy("system");
            loginLog.setCreateTime(LocalDateTime.now());
            
            // 保存日志
            sysLoginLogMapper.insert(loginLog);
            
        } catch (Exception e) {
            log.error("记录登录成功日志失败", e);
        }
    }
    
    /**
     * 记录登录失败日志
     */
    public void recordLoginFailure(String loginName, String failureReason, HttpServletRequest request) {
        try {
            SysLoginLog loginLog = new SysLoginLog();
            
            // 基础信息
            loginLog.setLoginName(loginName);
            loginLog.setLoginStatus("1");
            loginLog.setLoginTime(LocalDateTime.now());
            loginLog.setFailureReason(failureReason);
            
            // 网络信息
            loginLog.setLoginIp(getClientIP(request));
            loginLog.setLoginAddress(getAddressByIP(loginLog.getLoginIp()));
            
            // 客户端信息
            loginLog.setClientType(getClientType(request));
            loginLog.setUserAgent(request.getHeader("User-Agent"));
            loginLog.setBrowser(getBrowserInfo(request));
            loginLog.setOs(getOSInfo(request));
            loginLog.setDeviceName(getDeviceName(request));
            
            // 其他信息
            loginLog.setRemark("登录失败:" + failureReason);
            loginLog.setCreateBy("system");
            loginLog.setCreateTime(LocalDateTime.now());
            
            // 保存日志
            sysLoginLogMapper.insert(loginLog);
            
        } catch (Exception e) {
            log.error("记录登录失败日志失败", e);
        }
    }
    
    /**
     * 记录退出登录日志
     */
    public void recordLogout(String loginName, LocalDateTime loginTime) {
        try {
            // 查找对应的登录日志
            SysLoginLog loginLog = sysLoginLogMapper.selectOne(
                new LambdaQueryWrapper<SysLoginLog>()
                    .eq(SysLoginLog::getLoginName, loginName)
                    .eq(SysLoginLog::getLoginTime, loginTime)
                    .eq(SysLoginLog::getLoginStatus, "0")
                    .isNull(SysLoginLog::getLogoutTime)
                    .last("ORDER BY create_time DESC LIMIT 1")
            );
            
            if (loginLog != null) {
                LocalDateTime logoutTime = LocalDateTime.now();
                long sessionDuration = Duration.between(loginLog.getLoginTime(), logoutTime).getSeconds();
                
                loginLog.setLogoutTime(logoutTime);
                loginLog.setSessionDuration((int) sessionDuration);
                loginLog.setRemark("正常退出");
                loginLog.setUpdateBy("system");
                loginLog.setUpdateTime(LocalDateTime.now());
                
                sysLoginLogMapper.updateById(loginLog);
            }
            
        } catch (Exception e) {
            log.error("记录退出登录日志失败", e);
        }
    }
    
    /**
     * 获取客户端IP
     */
    private String getClientIP(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }
    
    /**
     * 解析浏览器信息
     */
    private String getBrowserInfo(HttpServletRequest request) {
        String userAgent = request.getHeader("User-Agent");
        if (userAgent == null) {
            return "Unknown";
        }
        
        if (userAgent.contains("Chrome")) {
            return "Chrome";
        } else if (userAgent.contains("Firefox")) {
            return "Firefox";
        } else if (userAgent.contains("Safari")) {
            return "Safari";
        } else if (userAgent.contains("Edge")) {
            return "Edge";
        } else if (userAgent.contains("IE")) {
            return "Internet Explorer";
        } else {
            return "Other";
        }
    }
    
    /**
     * 解析操作系统信息
     */
    private String getOSInfo(HttpServletRequest request) {
        String userAgent = request.getHeader("User-Agent");
        if (userAgent == null) {
            return "Unknown";
        }
        
        if (userAgent.contains("Windows NT 10.0")) {
            return "Windows 10";
        } else if (userAgent.contains("Windows NT 6.3")) {
            return "Windows 8.1";
        } else if (userAgent.contains("Windows NT 6.2")) {
            return "Windows 8";
        } else if (userAgent.contains("Windows NT 6.1")) {
            return "Windows 7";
        } else if (userAgent.contains("Mac OS X")) {
            return "Mac OS";
        } else if (userAgent.contains("Linux")) {
            return "Linux";
        } else if (userAgent.contains("Android")) {
            return "Android";
        } else if (userAgent.contains("iPhone") || userAgent.contains("iPad")) {
            return "iOS";
        } else {
            return "Other";
        }
    }
}

2. 异步处理

@Service
public class AsyncLoginLogService {
    
    @Async("taskExecutor")
    public void recordLoginLogAsync(SysLoginLog loginLog) {
        try {
            // 异步记录登录日志
            sysLoginLogMapper.insert(loginLog);
            
            // 更新用户登录信息
            updateUserLoginInfo(loginLog);
            
            // 检查异常登录
            checkAbnormalLogin(loginLog);
            
        } catch (Exception e) {
            log.error("异步记录登录日志失败", e);
        }
    }
    
    /**
     * 检查异常登录
     */
    private void checkAbnormalLogin(SysLoginLog loginLog) {
        // 检查IP异常
        if (isAbnormalIP(loginLog.getLoginIp(), loginLog.getLoginName())) {
            sendSecurityAlert("检测到异常IP登录", loginLog);
        }
        
        // 检查设备异常
        if (isAbnormalDevice(loginLog.getUserAgent(), loginLog.getLoginName())) {
            sendSecurityAlert("检测到异常设备登录", loginLog);
        }
        
        // 检查时间异常
        if (isAbnormalTime(loginLog.getLoginTime(), loginLog.getLoginName())) {
            sendSecurityAlert("检测到异常时间登录", loginLog);
        }
    }
}

统计分析功能

1. 登录统计

/**
 * 登录统计服务
 */
@Service
public class LoginStatisticsService {
    
    /**
     * 获取登录成功率统计
     */
    public LoginSuccessRateVO getLoginSuccessRate(String beginTime, String endTime) {
        // 查询总登录次数
        long totalCount = sysLoginLogMapper.selectCount(
            new LambdaQueryWrapper<SysLoginLog>()
                .between(SysLoginLog::getLoginTime, beginTime, endTime)
        );
        
        // 查询成功登录次数
        long successCount = sysLoginLogMapper.selectCount(
            new LambdaQueryWrapper<SysLoginLog>()
                .eq(SysLoginLog::getLoginStatus, "0")
                .between(SysLoginLog::getLoginTime, beginTime, endTime)
        );
        
        // 计算成功率
        double successRate = totalCount > 0 ? (double) successCount / totalCount * 100 : 0;
        
        return LoginSuccessRateVO.builder()
                .totalCount(totalCount)
                .successCount(successCount)
                .failureCount(totalCount - successCount)
                .successRate(successRate)
                .build();
    }
    
    /**
     * 获取每日登录统计
     */
    public List<DailyLoginStatVO> getDailyLoginStat(String beginTime, String endTime) {
        return sysLoginLogMapper.selectDailyLoginStat(beginTime, endTime);
    }
    
    /**
     * 获取客户端类型统计
     */
    public List<ClientTypeStatVO> getClientTypeStat(String beginTime, String endTime) {
        return sysLoginLogMapper.selectClientTypeStat(beginTime, endTime);
    }
}

2. 安全监控

/**
 * 安全监控服务
 */
@Service
public class SecurityMonitorService {
    
    /**
     * 检测暴力破解
     */
    public void detectBruteForce() {
        // 查询5分钟内失败次数超过5次的IP
        List<String> suspiciousIPs = sysLoginLogMapper.selectSuspiciousIPs();
        
        for (String ip : suspiciousIPs) {
            // 加入黑名单
            addToBlacklist(ip);
            
            // 发送告警
            sendSecurityAlert("检测到暴力破解攻击", ip);
        }
    }
    
    /**
     * 检测异地登录
     */
    public void detectRemoteLogin() {
        // 查询用户最近登录地址
        List<SysLoginLog> recentLogins = sysLoginLogMapper.selectRecentLogins();
        
        for (SysLoginLog loginLog : recentLogins) {
            String lastLoginAddress = getLastLoginAddress(loginLog.getLoginName());
            
            if (!loginLog.getLoginAddress().equals(lastLoginAddress)) {
                // 发送异地登录通知
                sendRemoteLoginNotification(loginLog);
            }
        }
    }
}

错误码说明

错误码 错误信息 说明
400 登录账号不能为空 登录账号为空
400 登录状态不能为空 登录状态为空
400 登录时间不能为空 登录时间为空
400 登录IP不能为空 登录IP为空
400 日志不存在 日志ID不存在
400 时间格式错误 时间格式不正确
401 当前会话未登录 未登录或Token无效
403 权限不足 没有相应的操作权限
500 日志记录失败 日志保存失败
500 系统异常 服务器内部错误

日志清理策略

1. 定时清理

@Component
public class LoginLogCleanupTask {
    
    /**
     * 每天凌晨2点清理30天前的登录日志
     */
    @Scheduled(cron = "0 0 2 * * ?")
    public void cleanupOldLogs() {
        try {
            LocalDateTime cutoffTime = LocalDateTime.now().minusDays(30);
            
            int deletedCount = sysLoginLogMapper.delete(
                new LambdaQueryWrapper<SysLoginLog>()
                    .lt(SysLoginLog::getCreateTime, cutoffTime)
            );
            
            log.info("清理登录日志完成,删除{}条记录", deletedCount);
            
        } catch (Exception e) {
            log.error("清理登录日志失败", e);
        }
    }
    
    /**
     * 归档登录日志
     */
    @Scheduled(cron = "0 0 1 1 * ?") // 每月1号凌晨1点执行
    public void archiveLogs() {
        try {
            LocalDateTime lastMonth = LocalDateTime.now().minusMonths(1);
            
            // 归档上个月的日志到历史表
            sysLoginLogMapper.archiveLogsToHistory(lastMonth);
            
            log.info("归档登录日志完成");
            
        } catch (Exception e) {
            log.error("归档登录日志失败", e);
        }
    }
}

2. 日志配置

# application.yml
logging:
  login-log:
    # 是否启用登录日志
    enabled: true
    # 日志保留天数
    retention-days: 90
    # 是否记录成功登录
    log-success: true
    # 是否记录失败登录
    log-failure: true
    # 是否异步记录
    async: true
    # 是否启用IP地址解析
    resolve-address: true
    # 是否启用安全监控
    security-monitor: true

使用建议

1. 日志管理

  • 合理保留期: 根据业务需要设置日志保留期
  • 定期清理: 定期清理过期日志释放存储空间
  • 分表存储: 大量日志可考虑按月分表存储
  • 归档备份: 重要日志定期归档备份

2. 安全监控

  • 实时监控: 实时监控异常登录行为
  • 告警机制: 建立完善的安全告警机制
  • 自动响应: 对可疑行为自动采取防护措施
  • 定期分析: 定期分析登录日志发现安全趋势

3. 性能优化

  • 异步记录: 使用异步方式记录日志避免影响登录性能
  • 批量处理: 批量处理日志数据提高效率
  • 索引优化: 为查询字段建立合适索引
  • 分页查询: 大数据量查询使用分页

4. 隐私保护

  • 敏感信息: 不记录密码等敏感信息
  • 数据脱敏: 对部分信息进行脱敏处理
  • 访问控制: 严格控制日志访问权限
  • 合规要求: 遵守相关数据保护法规

注意事项

  1. 日志完整性: 确保登录日志记录的完整性和准确性
  2. 性能影响: 日志记录不应影响用户登录体验
  3. 存储空间: 注意日志存储空间的管理和清理
  4. 安全防护: 防止日志被恶意篡改或删除
  5. 隐私保护: 不记录用户密码等敏感信息
  6. 异常处理: 日志记录失败不应影响正常业务
  7. 监控告警: 建立异常登录的监控告警机制
  8. 数据备份: 重要日志数据需要备份
  9. 合规要求: 遵守相关法律法规对日志的要求
  10. 访问审计: 对日志访问行为也要进行审计