# 登录日志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 | **响应示例**: ```json { "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" } ``` **调用示例**: ```bash 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外) **响应示例**: ```json { "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" } ``` **调用示例**: ```bash 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 | **响应示例**: ```json { "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" } ``` **调用示例**: ```bash curl -X GET \ http://localhost:18099/coder/sysLoginLog/getById/1 \ -H "Authorization: Bearer your-token-value" ``` --- ### 4. 新增登录日志 **接口地址**: `POST /coder/sysLoginLog/add` **接口描述**: 新增系统登录日志记录 **是否需要认证**: 是 **权限要求**: `system:loginlog:add` **请求参数**: ```json { "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字符 | **响应示例**: ```json { "status": 200, "msg": "SUCCESS", "data": "新增成功", "traceId": "trace-123456" } ``` **调用示例**: ```bash 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` **请求参数**: ```json { "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 | | 其他参数 | - | - | 同新增日志 | - | **响应示例**: ```json { "status": 200, "msg": "SUCCESS", "data": "修改成功", "traceId": "trace-123456" } ``` **调用示例**: ```bash 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 | **响应示例**: ```json { "status": 200, "msg": "SUCCESS", "data": "删除成功", "traceId": "trace-123456" } ``` **调用示例**: ```bash curl -X POST \ http://localhost:18099/coder/sysLoginLog/deleteById/1 \ -H "Authorization: Bearer your-token-value" ``` --- ### 7. 批量删除登录日志 **接口地址**: `POST /coder/sysLoginLog/batchDelete` **接口描述**: 批量删除登录日志 **是否需要认证**: 是 **权限要求**: `system:loginlog:remove` **请求参数**: ```json { "ids": [1, 2, 3] } ``` **请求参数说明**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | ids | Long[] | 是 | 日志ID数组 | **响应示例**: ```json { "status": 200, "msg": "SUCCESS", "data": "删除成功", "traceId": "trace-123456" } ``` **调用示例**: ```bash 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. 自动记录 ```java @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() .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. 异步处理 ```java @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. 登录统计 ```java /** * 登录统计服务 */ @Service public class LoginStatisticsService { /** * 获取登录成功率统计 */ public LoginSuccessRateVO getLoginSuccessRate(String beginTime, String endTime) { // 查询总登录次数 long totalCount = sysLoginLogMapper.selectCount( new LambdaQueryWrapper() .between(SysLoginLog::getLoginTime, beginTime, endTime) ); // 查询成功登录次数 long successCount = sysLoginLogMapper.selectCount( new LambdaQueryWrapper() .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 getDailyLoginStat(String beginTime, String endTime) { return sysLoginLogMapper.selectDailyLoginStat(beginTime, endTime); } /** * 获取客户端类型统计 */ public List getClientTypeStat(String beginTime, String endTime) { return sysLoginLogMapper.selectClientTypeStat(beginTime, endTime); } } ``` ### 2. 安全监控 ```java /** * 安全监控服务 */ @Service public class SecurityMonitorService { /** * 检测暴力破解 */ public void detectBruteForce() { // 查询5分钟内失败次数超过5次的IP List suspiciousIPs = sysLoginLogMapper.selectSuspiciousIPs(); for (String ip : suspiciousIPs) { // 加入黑名单 addToBlacklist(ip); // 发送告警 sendSecurityAlert("检测到暴力破解攻击", ip); } } /** * 检测异地登录 */ public void detectRemoteLogin() { // 查询用户最近登录地址 List 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. 定时清理 ```java @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() .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. 日志配置 ```yaml # 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. **访问审计**: 对日志访问行为也要进行审计