diff --git a/document/db/MySQL/qiaoba-boot-MySQL5.7.sql b/document/db/MySQL/qiaoba-boot-MySQL5.7.sql index 37cd80d..7ec4503 100644 --- a/document/db/MySQL/qiaoba-boot-MySQL5.7.sql +++ b/document/db/MySQL/qiaoba-boot-MySQL5.7.sql @@ -11,7 +11,7 @@ Target Server Version : 50742 File Encoding : 65001 - Date: 15/06/2023 16:11:20 + Date: 19/06/2023 17:23:51 */ SET NAMES utf8mb4; @@ -47,6 +47,8 @@ INSERT INTO `sys_config` VALUES (1661603968779079682, '主框架页-侧边栏主 INSERT INTO `sys_config` VALUES (1661603968779079683, '主框架页-默认皮肤样式名称', 'sys.index.skinName', 'skin-blue', 'Y', 'admin', '2022-08-15 18:01:28', '', NULL, '蓝色 skin-blue、绿色 skin-green、紫色 skin-purple、红色 skin-red、黄色 skin-yellow', 1); INSERT INTO `sys_config` VALUES (1668426274817994753, '登陆最大错误次数', 'sys.account.loginErrorMaxCount', '10', 'Y', 'admin', '2023-06-13 09:13:16', 'admin', '2023-06-13 09:35:59', '超过次数, 就会被拉黑', 1); INSERT INTO `sys_config` VALUES (1668428263694135297, '黑名单过期时间', 'sys.account.blacklistExpireTime', '30', 'Y', 'admin', '2023-06-13 09:21:11', 'admin', '2023-06-13 09:35:29', '拉黑时间, 单位:分钟, 仅支持正整数', 1); +INSERT INTO `sys_config` VALUES (1670692775595900930, '登录日志开关', 'sys.login.loginLogOnOff', 'true', 'Y', 'admin', '2023-06-19 15:19:32', 'admin', '2023-06-19 15:34:42', '登录日志开关', 1); +INSERT INTO `sys_config` VALUES (1670696367736258562, '账号同时在线开关', 'sys.account.allowBothOnline', 'false', 'Y', 'admin', '2023-06-19 15:33:49', 'admin', '2023-06-19 15:34:51', '同时在线开关', 1); -- ---------------------------- -- Table structure for sys_dept @@ -135,6 +137,35 @@ CREATE TABLE `sys_dict_type` ( INSERT INTO `sys_dict_type` VALUES (1665578778676703234, '测试', 'test', '1', 'admin', '2023-06-05 12:38:20', '', NULL, NULL, 1); INSERT INTO `sys_dict_type` VALUES (1665587609699889154, '测试2', '测试2', '1', 'admin', '2023-06-05 13:13:26', '', NULL, NULL, 1); +-- ---------------------------- +-- Table structure for sys_login_log +-- ---------------------------- +DROP TABLE IF EXISTS `sys_login_log`; +CREATE TABLE `sys_login_log` ( + `login_id` bigint(20) NOT NULL, + `device_sn` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '设备编码', + `username` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '登录账号', + `nickname` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户名称', + `ip` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '访问IP', + `address` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '登录地点', + `browser` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '浏览器', + `os` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '操作系统', + `login_time` datetime NULL DEFAULT NULL COMMENT '登录时间', + `create_user` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `update_user` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + `remark` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注', + `tenant_id` bigint(20) NULL DEFAULT NULL, + PRIMARY KEY (`login_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '登录日志' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_login_log +-- ---------------------------- +INSERT INTO `sys_login_log` VALUES (1670722570643869697, '34ca854d3c1549318b9f7b2923faf4f7', 'admin', '小王', '192.168.0.201', '0|0|0|内网IP|内网IP', 'Chrome|114.0.0.0', 'Windows 10 or Windows Server 2016', '2023-06-19 17:17:56', '', NULL, '', NULL, NULL, 1); +INSERT INTO `sys_login_log` VALUES (1670723605751959554, 'b9c055b82943483799feab5a1c0e0f46', 'admin', '小王', '192.168.0.201', '0|0|0|内网IP|内网IP', 'Chrome|114.0.0.0', 'Windows 10 or Windows Server 2016', '2023-06-19 17:22:03', '', NULL, '', NULL, NULL, 1); + -- ---------------------------- -- Table structure for sys_menu -- ---------------------------- @@ -174,7 +205,7 @@ INSERT INTO `sys_menu` VALUES (103, '部门管理', 1, 4, 'dept', 'system/dept/i INSERT INTO `sys_menu` VALUES (104, '岗位管理', 1, 5, 'post', 'system/post/index', '', 0, 0, 'C', '1', 'system:post:list', 'post', 'admin', '2023-04-23 14:35:29', '', NULL, '岗位管理菜单', 1); INSERT INTO `sys_menu` VALUES (105, '字典管理', 1, 6, 'dict', 'system/dict/index', '', 0, 0, 'C', '1', 'system:dict:list', 'documentation', 'admin', '2022-08-15 18:01:28', 'admin', '2023-05-31 11:15:14', '字典管理菜单', 1); INSERT INTO `sys_menu` VALUES (106, '参数设置', 1, 7, 'config', 'system/config/index', '', 0, 0, 'C', '1', 'system:config:list', 'edit', 'admin', '2022-08-15 18:01:28', 'admin', '2023-05-24 21:13:11', '参数设置菜单', 1); -INSERT INTO `sys_menu` VALUES (109, '登录用户', 2, 1, 'online', 'monitor/online/index', '', 0, 0, 'C', '1', 'monitor:online:list', 'online', 'admin', '2023-05-27 22:22:18', 'admin', '2023-05-30 09:49:35', '在线用户菜单', 1); +INSERT INTO `sys_menu` VALUES (109, '在线用户', 2, 1, 'online', 'monitor/online/index', '', 0, 0, 'C', '1', 'monitor:online:list', 'online', 'admin', '2023-05-27 22:22:18', 'admin', '2023-06-19 15:29:03', '在线用户菜单', 1); INSERT INTO `sys_menu` VALUES (1000, '用户查询', 100, 1, '', '', '', 0, 0, 'F', '1', 'system:user:query', '#', 'admin', '2023-04-23 14:35:29', '', NULL, '', 1); INSERT INTO `sys_menu` VALUES (1001, '用户新增', 100, 2, '', '', '', 0, 0, 'F', '1', 'system:user:add', '#', 'admin', '2023-04-23 14:35:29', '', NULL, '', 1); INSERT INTO `sys_menu` VALUES (1002, '用户修改', 100, 3, '', '', '', 0, 0, 'F', '1', 'system:user:edit', '#', 'admin', '2023-04-23 14:35:29', '', NULL, '', 1); @@ -223,6 +254,9 @@ INSERT INTO `sys_menu` VALUES (1666365996601196545, '数据源列表', 166343193 INSERT INTO `sys_menu` VALUES (1666366412382552066, '删除租户', 1663431933531869185, 4, '', NULL, NULL, 0, 0, 'F', '1', 'tenant:remove', '#', 'admin', '2023-06-07 16:48:07', 'admin', '2023-06-13 16:52:20', '', 1); INSERT INTO `sys_menu` VALUES (1668543448450719745, '租户管理', 0, 3, 'tenant', NULL, NULL, 0, 0, 'M', '1', NULL, 'component', 'admin', '2023-06-13 16:58:53', 'admin', '2023-06-13 17:03:42', '', 1); INSERT INTO `sys_menu` VALUES (1668544169384468481, '租户初始化', 1668543448450719745, 2, 'initialize', 'tenant/initialize', NULL, 0, 0, 'C', '0', NULL, '#', 'admin', '2023-06-13 17:01:45', 'admin', '2023-06-13 17:03:49', '', 1); +INSERT INTO `sys_menu` VALUES (1670708064303742978, '登录日志', 2, 2, 'login-log', 'monitor/login_log/index', NULL, 0, 0, 'C', '1', 'monitor:login-log:list', 'documentation', 'admin', '2023-06-19 16:20:17', 'admin', '2023-06-19 16:21:59', '', 1); +INSERT INTO `sys_menu` VALUES (1670719944372002817, '日志导出', 1670708064303742978, 1, '', NULL, NULL, 0, 0, 'F', '1', 'monitor:login-log:export', '#', 'admin', '2023-06-19 17:07:30', '', NULL, '', 1); +INSERT INTO `sys_menu` VALUES (1670720034851528706, '日志清空', 1670708064303742978, 2, '', NULL, NULL, 0, 0, 'F', '1', 'monitor:login-log:remove', '#', 'admin', '2023-06-19 17:07:51', '', NULL, '', 1); -- ---------------------------- -- Table structure for sys_post @@ -274,7 +308,7 @@ CREATE TABLE `sys_role` ( -- ---------------------------- -- Records of sys_role -- ---------------------------- -INSERT INTO `sys_role` VALUES (1, '超级管理员', 'admin', 1, '1', '1', 'admin', '2023-04-23 14:35:29', 'admin', '2023-06-13 17:02:24', '超级管理员', 1); +INSERT INTO `sys_role` VALUES (1, '超级管理员', 'admin', 1, '1', '1', 'admin', '2023-04-23 14:35:29', 'admin', '2023-06-19 17:08:04', '超级管理员', 1); INSERT INTO `sys_role` VALUES (1660535591067213826, '测试', 'test', 1, '4', '1', 'admin', '2023-05-22 14:38:31', 'admin', '2023-06-15 16:05:49', NULL, 1); -- ---------------------------- @@ -364,6 +398,9 @@ INSERT INTO `sys_role_menu` VALUES (1, 1666365996601196545, 1); INSERT INTO `sys_role_menu` VALUES (1, 1666366412382552066, 1); INSERT INTO `sys_role_menu` VALUES (1, 1668543448450719745, 1); INSERT INTO `sys_role_menu` VALUES (1, 1668544169384468481, 1); +INSERT INTO `sys_role_menu` VALUES (1, 1670708064303742978, 1); +INSERT INTO `sys_role_menu` VALUES (1, 1670719944372002817, 1); +INSERT INTO `sys_role_menu` VALUES (1, 1670720034851528706, 1); INSERT INTO `sys_role_menu` VALUES (1660535591067213826, 1, 1); INSERT INTO `sys_role_menu` VALUES (1660535591067213826, 2, 1); INSERT INTO `sys_role_menu` VALUES (1660535591067213826, 100, 1); diff --git a/document/db/PostgreSQL/qiaoba-boot-PostgreSQL14.sql b/document/db/PostgreSQL/qiaoba-boot-PostgreSQL14.sql index 7bd871e..2ac2fd5 100644 --- a/document/db/PostgreSQL/qiaoba-boot-PostgreSQL14.sql +++ b/document/db/PostgreSQL/qiaoba-boot-PostgreSQL14.sql @@ -12,7 +12,7 @@ Target Server Version : 140008 File Encoding : 65001 - Date: 15/06/2023 16:09:50 + Date: 19/06/2023 17:25:53 */ @@ -186,6 +186,49 @@ COMMENT ON TABLE "qiaoba-boot"."sys_dict_type" IS '字典类型表'; INSERT INTO "qiaoba-boot"."sys_dict_type" VALUES ('1665578778676703234', '测试', 'test', '1', 'admin', '2023-06-05 12:38:20', '', NULL, NULL, '1'); INSERT INTO "qiaoba-boot"."sys_dict_type" VALUES ('1665587609699889154', '测试2', '测试2', '1', 'admin', '2023-06-05 13:13:26', '', NULL, NULL, '1'); +-- ---------------------------- +-- Table structure for sys_login_log +-- ---------------------------- +DROP TABLE IF EXISTS "qiaoba-boot"."sys_login_log"; +CREATE TABLE "qiaoba-boot"."sys_login_log" ( + "login_id" varchar(64) COLLATE "pg_catalog"."default" NOT NULL, + "device_sn" varchar(50) COLLATE "pg_catalog"."default", + "username" varchar(50) COLLATE "pg_catalog"."default", + "nickname" varchar(30) COLLATE "pg_catalog"."default", + "ip" varchar(30) COLLATE "pg_catalog"."default", + "address" varchar(255) COLLATE "pg_catalog"."default", + "browser" varchar(50) COLLATE "pg_catalog"."default", + "os" varchar(50) COLLATE "pg_catalog"."default", + "login_time" timestamp(6), + "create_user" varchar(64) COLLATE "pg_catalog"."default", + "create_time" timestamp(6), + "update_user" varchar(64) COLLATE "pg_catalog"."default", + "update_time" timestamp(6), + "remark" varchar(500) COLLATE "pg_catalog"."default", + "tenant_id" varchar(64) COLLATE "pg_catalog"."default" +) +; +COMMENT ON COLUMN "qiaoba-boot"."sys_login_log"."device_sn" IS '设备编码'; +COMMENT ON COLUMN "qiaoba-boot"."sys_login_log"."username" IS '登录账号'; +COMMENT ON COLUMN "qiaoba-boot"."sys_login_log"."nickname" IS '用户名称'; +COMMENT ON COLUMN "qiaoba-boot"."sys_login_log"."ip" IS '访问IP'; +COMMENT ON COLUMN "qiaoba-boot"."sys_login_log"."address" IS '登录地点'; +COMMENT ON COLUMN "qiaoba-boot"."sys_login_log"."browser" IS '浏览器'; +COMMENT ON COLUMN "qiaoba-boot"."sys_login_log"."os" IS '操作系统'; +COMMENT ON COLUMN "qiaoba-boot"."sys_login_log"."login_time" IS '登录时间'; +COMMENT ON COLUMN "qiaoba-boot"."sys_login_log"."create_user" IS '创建者'; +COMMENT ON COLUMN "qiaoba-boot"."sys_login_log"."create_time" IS '创建时间'; +COMMENT ON COLUMN "qiaoba-boot"."sys_login_log"."update_user" IS '更新者'; +COMMENT ON COLUMN "qiaoba-boot"."sys_login_log"."update_time" IS '更新时间'; +COMMENT ON COLUMN "qiaoba-boot"."sys_login_log"."remark" IS '备注'; +COMMENT ON TABLE "qiaoba-boot"."sys_login_log" IS '登录日志'; + +-- ---------------------------- +-- Records of sys_login_log +-- ---------------------------- +INSERT INTO "qiaoba-boot"."sys_login_log" VALUES ('1670722570643869697', '34ca854d3c1549318b9f7b2923faf4f7', 'admin', '小王', '192.168.0.201', '0|0|0|内网IP|内网IP', 'Chrome|114.0.0.0', 'Windows 10 or Windows Server 2016', '2023-06-19 17:17:56', '', NULL, '', NULL, NULL, '1'); +INSERT INTO "qiaoba-boot"."sys_login_log" VALUES ('1670723605751959554', 'b9c055b82943483799feab5a1c0e0f46', 'admin', '小王', '192.168.0.201', '0|0|0|内网IP|内网IP', 'Chrome|114.0.0.0', 'Windows 10 or Windows Server 2016', '2023-06-19 17:22:03', '', NULL, '', NULL, NULL, '1'); + -- ---------------------------- -- Table structure for sys_menu -- ---------------------------- @@ -743,6 +786,11 @@ CREATE INDEX "dict_type" ON "qiaoba-boot"."sys_dict_type" USING btree ( -- ---------------------------- ALTER TABLE "qiaoba-boot"."sys_dict_type" ADD CONSTRAINT "sys_dict_type_pkey" PRIMARY KEY ("dict_id"); +-- ---------------------------- +-- Primary Key structure for table sys_login_log +-- ---------------------------- +ALTER TABLE "qiaoba-boot"."sys_login_log" ADD CONSTRAINT "sys_login_log_pkey" PRIMARY KEY ("login_id"); + -- ---------------------------- -- Primary Key structure for table sys_menu -- ---------------------------- diff --git a/pom.xml b/pom.xml index 7023c9e..5aef5f7 100644 --- a/pom.xml +++ b/pom.xml @@ -190,6 +190,11 @@ qiaoba-api-file ${qiaoba.version} + + com.qiaoba + qiaoba-api-monitor + ${qiaoba.version} + diff --git a/qiaoba-apis/pom.xml b/qiaoba-apis/pom.xml index cf81d10..2d0043c 100644 --- a/qiaoba-apis/pom.xml +++ b/qiaoba-apis/pom.xml @@ -16,6 +16,7 @@ qiaoba-api-job qiaoba-api-file qiaoba-api-auth + qiaoba-api-monitor diff --git a/qiaoba-apis/qiaoba-api-monitor/pom.xml b/qiaoba-apis/qiaoba-api-monitor/pom.xml new file mode 100644 index 0000000..059d4cb --- /dev/null +++ b/qiaoba-apis/qiaoba-api-monitor/pom.xml @@ -0,0 +1,28 @@ + + + + qiaoba-apis + com.qiaoba + 1.0 + + 4.0.0 + + qiaoba-api-monitor + + + + com.qiaoba + qiaoba-auth + + + com.qiaoba + qiaoba-common-poi + + + com.qiaoba + qiaoba-common-datasource + + + diff --git a/qiaoba-apis/qiaoba-api-monitor/src/main/java/com/qiaoba/api/monitor/entity/SysLoginLog.java b/qiaoba-apis/qiaoba-api-monitor/src/main/java/com/qiaoba/api/monitor/entity/SysLoginLog.java new file mode 100644 index 0000000..c21586c --- /dev/null +++ b/qiaoba-apis/qiaoba-api-monitor/src/main/java/com/qiaoba/api/monitor/entity/SysLoginLog.java @@ -0,0 +1,52 @@ +package com.qiaoba.api.monitor.entity; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.qiaoba.common.base.entity.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +/** + * 登录日志 + * + * @author ailanyin + * @version 1.0 + * @since 2023/6/19 14:31 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("sys_login_log") +public class SysLoginLog extends BaseEntity { + + private static final long serialVersionUID = 1L; + + @TableId + private String loginId; + + @Excel(name = "会话编号", width = 25) + private String deviceSn; + + @Excel(name = "登录账号", width = 25) + private String username; + + @Excel(name = "用户名称", width = 25) + private String nickname; + + @Excel(name = "访问IP", width = 25) + private String ip; + + @Excel(name = "登录地点", width = 25) + private String address; + + @Excel(name = "浏览器", width = 30) + private String browser; + + @Excel(name = "操作系统", width = 20) + private String os; + + @Excel(name = "登录时间", format = "yyyy-MM-dd HH:mm:ss", width = 30) + private Date loginTime; +} diff --git a/qiaoba-apis/qiaoba-api-monitor/src/main/java/com/qiaoba/api/monitor/entity/param/LoginLogParam.java b/qiaoba-apis/qiaoba-api-monitor/src/main/java/com/qiaoba/api/monitor/entity/param/LoginLogParam.java new file mode 100644 index 0000000..45e7f23 --- /dev/null +++ b/qiaoba-apis/qiaoba-api-monitor/src/main/java/com/qiaoba/api/monitor/entity/param/LoginLogParam.java @@ -0,0 +1,32 @@ +package com.qiaoba.api.monitor.entity.param; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.format.annotation.DateTimeFormat; + +import java.io.Serializable; +import java.util.Date; + +/** + * 登录日志查询参数 + * + * @author ailanyin + * @version 1.0 + * @since 2023/6/19 15:59 + */ +@Getter +@Setter +public class LoginLogParam implements Serializable { + + private String username; + + private String nickname; + + private String ip; + + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date beginTime; + + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date endTime; +} diff --git a/qiaoba-apis/qiaoba-api-monitor/src/main/java/com/qiaoba/api/monitor/service/SysLoginLogApiService.java b/qiaoba-apis/qiaoba-api-monitor/src/main/java/com/qiaoba/api/monitor/service/SysLoginLogApiService.java new file mode 100644 index 0000000..561535e --- /dev/null +++ b/qiaoba-apis/qiaoba-api-monitor/src/main/java/com/qiaoba/api/monitor/service/SysLoginLogApiService.java @@ -0,0 +1,21 @@ +package com.qiaoba.api.monitor.service; + +import com.qiaoba.api.monitor.entity.SysLoginLog; + +/** + * 登录日志 对外暴露接口 + * + * @author ailanyin + * @version 1.0 + * @since 2023/6/19 15:50 + */ +public interface SysLoginLogApiService { + + /** + * 新增 + * + * @param sysLoginLog sysLoginLog + * @return 结果 + */ + Integer insert(SysLoginLog sysLoginLog); +} diff --git a/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/constants/ConfigConstant.java b/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/constants/ConfigConstant.java index 51eb237..2ca6879 100644 --- a/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/constants/ConfigConstant.java +++ b/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/constants/ConfigConstant.java @@ -49,6 +49,11 @@ public class ConfigConstant { */ public static final String LOGIN_ERROR_MAX_COUNT_KEY = SYS_CONFIG_KEY_PREFIX + "sys.account.loginErrorMaxCount"; + /** + * 参数配置-登录日志开关 + */ + public static final String LOGIN_LOG_ON_OFF_KEY = SYS_CONFIG_KEY_PREFIX + "sys.login.loginLogOnOff"; + /** * 开 */ diff --git a/qiaoba-modules/qiaoba-module-monitor/pom.xml b/qiaoba-modules/qiaoba-module-monitor/pom.xml index 33e07f0..a2e4d21 100644 --- a/qiaoba-modules/qiaoba-module-monitor/pom.xml +++ b/qiaoba-modules/qiaoba-module-monitor/pom.xml @@ -24,5 +24,9 @@ com.qiaoba qiaoba-common-datasource + + com.qiaoba + qiaoba-api-monitor + - \ No newline at end of file + diff --git a/qiaoba-modules/qiaoba-module-monitor/src/main/java/com/qiaoba/module/monitor/controller/SysLoginLogController.java b/qiaoba-modules/qiaoba-module-monitor/src/main/java/com/qiaoba/module/monitor/controller/SysLoginLogController.java new file mode 100644 index 0000000..665945e --- /dev/null +++ b/qiaoba-modules/qiaoba-module-monitor/src/main/java/com/qiaoba/module/monitor/controller/SysLoginLogController.java @@ -0,0 +1,56 @@ +package com.qiaoba.module.monitor.controller; + +import com.qiaoba.api.monitor.entity.SysLoginLog; +import com.qiaoba.api.monitor.entity.param.LoginLogParam; +import com.qiaoba.common.base.result.AjaxResult; +import com.qiaoba.common.database.entity.PageQuery; +import com.qiaoba.common.database.entity.TableDataInfo; +import com.qiaoba.common.poi.utils.ExcelUtil; +import com.qiaoba.module.monitor.service.SysLoginLogService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import java.util.List; + +/** + * 登录日志管理 Web层 + * + * @author ailanyin + * @version 1.0 + * @since 2023-05-27 21:59:12 + */ +@RestController +@RequestMapping("/monitor/login-log") +@RequiredArgsConstructor +@Tag(name = "登录日志管理") +public class SysLoginLogController { + + private final SysLoginLogService sysLoginLogService; + + @GetMapping("/list") + @Operation(summary = "分页查询") + @PreAuthorize("hasAuthority('monitor:login-log:list')") + public TableDataInfo list(LoginLogParam param, PageQuery pageQuery) { + return sysLoginLogService.selectPageList(param, pageQuery); + } + + @PreAuthorize("hasAuthority('monitor:login-log:export')") + @PostMapping("/export") + @Operation(summary = "导出日志") + public void export(HttpServletResponse response, LoginLogParam param) { + List list = sysLoginLogService.selectList(param); + ExcelUtil.exportExcel(list, SysLoginLog.class, "登录日志", response); + } + + @PreAuthorize("hasAuthority('monitor:login-log:remove')") + @DeleteMapping("/clean") + @Operation(summary = "清空日志") + public AjaxResult clean() { + sysLoginLogService.cleanLoginLog(); + return AjaxResult.success(); + } +} diff --git a/qiaoba-modules/qiaoba-module-monitor/src/main/java/com/qiaoba/module/monitor/mapper/SysLoginLogMapper.java b/qiaoba-modules/qiaoba-module-monitor/src/main/java/com/qiaoba/module/monitor/mapper/SysLoginLogMapper.java new file mode 100644 index 0000000..07702a5 --- /dev/null +++ b/qiaoba-modules/qiaoba-module-monitor/src/main/java/com/qiaoba/module/monitor/mapper/SysLoginLogMapper.java @@ -0,0 +1,14 @@ +package com.qiaoba.module.monitor.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qiaoba.api.monitor.entity.SysLoginLog; + +/** + * 登录日志 数据层 + * + * @author ailanyin + * @version 1.0 + * @since 2023/6/19 14:41 + */ +public interface SysLoginLogMapper extends BaseMapper { +} diff --git a/qiaoba-modules/qiaoba-module-monitor/src/main/java/com/qiaoba/module/monitor/service/SysLoginLogService.java b/qiaoba-modules/qiaoba-module-monitor/src/main/java/com/qiaoba/module/monitor/service/SysLoginLogService.java new file mode 100644 index 0000000..027154d --- /dev/null +++ b/qiaoba-modules/qiaoba-module-monitor/src/main/java/com/qiaoba/module/monitor/service/SysLoginLogService.java @@ -0,0 +1,42 @@ +package com.qiaoba.module.monitor.service; + +import com.qiaoba.api.monitor.entity.SysLoginLog; +import com.qiaoba.api.monitor.entity.param.LoginLogParam; +import com.qiaoba.api.monitor.service.SysLoginLogApiService; +import com.qiaoba.common.database.entity.PageQuery; +import com.qiaoba.common.database.entity.TableDataInfo; + +import java.util.List; + +/** + * 登录日志 服务层 + * + * @author ailanyin + * @version 1.0 + * @since 2023/6/19 15:52 + */ +public interface SysLoginLogService extends SysLoginLogApiService { + + /** + * 分页查询 + * + * @param param 查询参数 + * @param pageQuery 分页参数 + * @return page + */ + TableDataInfo selectPageList(LoginLogParam param, PageQuery pageQuery); + + /** + * 清空日志 + */ + void cleanLoginLog(); + + /** + * 条件查询 + * + * @param param param + * @return list + */ + List selectList(LoginLogParam param); + +} diff --git a/qiaoba-modules/qiaoba-module-monitor/src/main/java/com/qiaoba/module/monitor/service/impl/SysLoginLogServiceImpl.java b/qiaoba-modules/qiaoba-module-monitor/src/main/java/com/qiaoba/module/monitor/service/impl/SysLoginLogServiceImpl.java new file mode 100644 index 0000000..2ddf5ef --- /dev/null +++ b/qiaoba-modules/qiaoba-module-monitor/src/main/java/com/qiaoba/module/monitor/service/impl/SysLoginLogServiceImpl.java @@ -0,0 +1,62 @@ +package com.qiaoba.module.monitor.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.qiaoba.api.monitor.entity.SysLoginLog; +import com.qiaoba.api.monitor.entity.param.LoginLogParam; +import com.qiaoba.common.database.entity.PageQuery; +import com.qiaoba.common.database.entity.TableDataInfo; +import com.qiaoba.module.monitor.mapper.SysLoginLogMapper; +import com.qiaoba.module.monitor.service.SysLoginLogService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Objects; + +/** + * 登录日志 服务层实现 + * + * @author ailanyin + * @version 1.0 + * @since 2023/6/19 14:39 + */ +@Service +@RequiredArgsConstructor +public class SysLoginLogServiceImpl implements SysLoginLogService { + + private final SysLoginLogMapper sysLoginLogMapper; + + @Override + public Integer insert(SysLoginLog sysLoginLog) { + return sysLoginLogMapper.insert(sysLoginLog); + } + + @Override + public TableDataInfo selectPageList(LoginLogParam param, PageQuery pageQuery) { + return TableDataInfo.build(sysLoginLogMapper.selectPage(pageQuery.build(), param2Wrapper(param))); + } + + @Override + public void cleanLoginLog() { + sysLoginLogMapper.delete(new QueryWrapper<>()); + } + + @Override + public List selectList(LoginLogParam param) { + return sysLoginLogMapper.selectList(param2Wrapper(param)); + } + + private QueryWrapper param2Wrapper(LoginLogParam param) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.lambda() + .orderByAsc(SysLoginLog::getLoginTime) + .ge(Objects.nonNull(param.getBeginTime()), SysLoginLog::getLoginTime, param.getBeginTime()) + .le(Objects.nonNull(param.getEndTime()), SysLoginLog::getLoginTime, param.getEndTime()) + .like(StrUtil.isNotBlank(param.getNickname()), SysLoginLog::getNickname, param.getNickname()) + .like(StrUtil.isNotBlank(param.getUsername()), SysLoginLog::getUsername, param.getUsername()) + .like(StrUtil.isNotBlank(param.getIp()), SysLoginLog::getIp, param.getIp()); + + return wrapper; + } +} diff --git a/qiaoba-modules/qiaoba-module-system/pom.xml b/qiaoba-modules/qiaoba-module-system/pom.xml index a8ddd91..e5270cf 100644 --- a/qiaoba-modules/qiaoba-module-system/pom.xml +++ b/qiaoba-modules/qiaoba-module-system/pom.xml @@ -24,5 +24,9 @@ com.qiaoba qiaoba-api-file + + com.qiaoba + qiaoba-api-monitor + diff --git a/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/impl/SysLoginServiceImpl.java b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/impl/SysLoginServiceImpl.java index 2d82bdf..b34b764 100644 --- a/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/impl/SysLoginServiceImpl.java +++ b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/impl/SysLoginServiceImpl.java @@ -2,6 +2,7 @@ package com.qiaoba.module.system.service.impl; import cn.hutool.captcha.CaptchaUtil; import cn.hutool.captcha.LineCaptcha; +import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.lang.UUID; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; @@ -9,6 +10,8 @@ import cn.hutool.http.useragent.UserAgent; import cn.hutool.http.useragent.UserAgentUtil; import com.qiaoba.api.auth.service.AuthConfigApiService; import com.qiaoba.api.auth.service.SysUserDetailsApiService; +import com.qiaoba.api.monitor.entity.SysLoginLog; +import com.qiaoba.api.monitor.service.SysLoginLogApiService; import com.qiaoba.api.system.entity.SysUser; import com.qiaoba.api.system.entity.dto.LoginDto; import com.qiaoba.auth.constants.SecurityConstant; @@ -17,6 +20,7 @@ import com.qiaoba.auth.service.OnlineUserService; import com.qiaoba.auth.utils.SecurityUtil; import com.qiaoba.auth.utils.TokenUtil; import com.qiaoba.common.base.constants.BaseConstant; +import com.qiaoba.common.base.constants.ConfigConstant; import com.qiaoba.common.base.enums.BaseEnum; import com.qiaoba.common.base.exceptions.ServiceException; import com.qiaoba.common.redis.service.RedisService; @@ -49,7 +53,7 @@ public class SysLoginServiceImpl implements SysLoginService { private final SysUserService sysUserService; private final OnlineUserService onlineUserService; private final AuthConfigApiService authConfigApiService; - + private final SysLoginLogApiService sysLoginLogApiService; @Override public Map getCaptchaImage() { @@ -84,11 +88,13 @@ public class SysLoginServiceImpl implements SysLoginService { // 检验密码 validatePassword(blacklistSwitch, dto.getUsername(), sysUser.getPassword(), dto.getPassword()); // 缓存在线用户 - String deviceSn = cacheOnlineUser(dto.getUsername(), sysUser.getNickname()); + OnlineUser onlineUser = cacheOnlineUser(dto.getUsername(), sysUser.getNickname()); // 缓存userDetails - userDetailsService.toCache(sysUser.getUsername(), deviceSn); + userDetailsService.toCache(sysUser.getUsername(), onlineUser.getDeviceSn()); + // 新增登录日志 + addLoginLog(onlineUser); // 生成Token - return TokenUtil.generateToken(sysUser.getUsername(), deviceSn); + return TokenUtil.generateToken(sysUser.getUsername(), onlineUser.getDeviceSn()); } private void validateBlacklist(Boolean blacklistSwitch) { @@ -100,10 +106,14 @@ public class SysLoginServiceImpl implements SysLoginService { private void validatePassword(Boolean blacklistSwitch, String username, String password, String inputPassword) { boolean result = SecurityUtil.matchesPassword(inputPassword, password); - if (result && blacklistSwitch) { - // 密码正确, 删除错误次数 - String ip = IpUtil.getIp(request); - redisService.del(SecurityConstant.LOGIN_ERROR_COUNT + ip); + // 密码正确 + if (result) { + if (blacklistSwitch) { + // 删除错误次数 + String ip = IpUtil.getIp(request); + redisService.del(SecurityConstant.LOGIN_ERROR_COUNT + ip); + } + } else { // 密码错误 String msg = beforePasswordError(blacklistSwitch, username); @@ -149,7 +159,7 @@ public class SysLoginServiceImpl implements SysLoginService { } - private String cacheOnlineUser(String username, String nickname) { + private OnlineUser cacheOnlineUser(String username, String nickname) { String deviceSn = UUID.fastUUID().toString(true); String ip = IpUtil.getIp(request); String address = IpUtil.getIpAddr(ip); @@ -160,8 +170,17 @@ public class SysLoginServiceImpl implements SysLoginService { if (!authConfigApiService.checkAllowBothOnline()) { redisService.set(SecurityConstant.LOGGED_USER_REDIS_KEY + username, deviceSn, TokenUtil.expireTime * 3600); } - onlineUserService.insert(new OnlineUser(deviceSn, username, nickname, ip, address, browser, os, new Date())); - return deviceSn; + OnlineUser onlineUser = new OnlineUser(deviceSn, username, nickname, ip, address, browser, os, new Date()); + onlineUserService.insert(onlineUser); + return onlineUser; } + private void addLoginLog(OnlineUser onlineUser) { + // 查询系统配置 - 是否开启登录日志 + String onOff = redisService.getObject(ConfigConstant.LOGIN_LOG_ON_OFF_KEY, String.class); + if (ConfigConstant.COMMON_ON_VALUE.equals(onOff)) { + SysLoginLog sysLoginLog = BeanUtil.copyProperties(onlineUser, SysLoginLog.class); + sysLoginLogApiService.insert(sysLoginLog); + } + } }