瀏覽代碼

优化登陆日志,增加 userId、userType,更多的 loginType

YunaiV 3 年之前
父節點
當前提交
79f9f7b93d

File diff suppressed because it is too large
+ 21 - 96
sql/ruoyi-vue-pro.sql


+ 4 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/loginlog/SysLoginLogExcelVO.java

@@ -20,6 +20,10 @@ public class SysLoginLogExcelVO {
     @ExcelProperty("用户账号")
     private String username;
 
+    @ExcelProperty(value = "日志类型", converter = DictConvert.class)
+    @DictFormat(SysDictTypeConstants.LOGIN_TYPE)
+    private Integer logType;
+
     @ExcelProperty(value = "登陆结果", converter = DictConvert.class)
     @DictFormat(SysDictTypeConstants.LOGIN_RESULT)
     private Integer result;

+ 9 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/loginlog/SysLoginLogRespVO.java

@@ -6,6 +6,7 @@ import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.ToString;
 
+import javax.validation.constraints.NotNull;
 import java.util.Date;
 
 @ApiModel("登陆日志 Response VO")
@@ -17,6 +18,14 @@ public class SysLoginLogRespVO extends SysLoginLogBaseVO {
     @ApiModelProperty(value = "日志编号", required = true, example = "1024")
     private Long id;
 
+    @ApiModelProperty(value = "用户编号", required = true, example = "666")
+    @NotNull(message = "用户编号不能为空")
+    private Long userId;
+
+    @ApiModelProperty(value = "用户类型", required = true, example = "2", notes = "参见 UserTypeEnum 枚举")
+    @NotNull(message = "用户类型不能为空")
+    private Integer userType;
+
     @ApiModelProperty(value = "登陆时间", required = true)
     private Date createTime;
 

+ 11 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/logger/SysLoginLogDO.java

@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.logger;
 
+import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
 import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginLogTypeEnum;
 import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginResultEnum;
@@ -36,6 +37,16 @@ public class SysLoginLogDO extends BaseDO {
      */
     private String traceId;
     /**
+     * 用户编号
+     */
+    private Long userId;
+    /**
+     * 用户类型
+     *
+     * 枚举 {@link UserTypeEnum}
+     */
+    private Integer userType;
+    /**
      * 用户账号
      *
      * 冗余,因为账号可以变更

+ 1 - 1
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/SysDictTypeConstants.java

@@ -12,6 +12,7 @@ public interface SysDictTypeConstants {
 
     String USER_SEX = "sys_user_sex"; // 用户性别
     String OPERATE_TYPE = "sys_operate_type"; // 操作类型
+    String LOGIN_TYPE = "sys_login_type"; // 登陆日志的类型
     String LOGIN_RESULT = "sys_login_result"; // 登陆结果
     String CONFIG_TYPE = "sys_config_type"; // 参数配置类型
     String BOOLEAN_STRING = "sys_boolean_string"; // Boolean 是否类型
@@ -21,5 +22,4 @@ public interface SysDictTypeConstants {
     String SMS_SEND_STATUS = "sys_sms_send_status"; // 短信发送状态
     String SMS_RECEIVE_STATUS = "sys_sms_receive_status"; // 短信接收状态
 
-
 }

+ 1 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/logger/SysLoginLogTypeEnum.java

@@ -12,6 +12,7 @@ public enum SysLoginLogTypeEnum {
 
     LOGIN_USERNAME(100), // 使用账号登录
     LOGIN_SOCIAL(101), // 使用社交登陆
+    LOGIN_MOCK(102), // 使用 Mock 登陆
 
     LOGOUT_SELF(200),  // 自己主动登出
     LOGOUT_TIMEOUT(201), // 超时登出

+ 28 - 25
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/SysAuthServiceImpl.java

@@ -1,18 +1,12 @@
 package cn.iocoder.yudao.adminserver.modules.system.service.auth.impl;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthLoginReqVO;
 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthSocialLogin2ReqVO;
 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthSocialLoginReqVO;
-import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.social.SysSocialUserDO;
-import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.social.SysSocialUserMapper;
-import cn.iocoder.yudao.adminserver.modules.system.service.social.SysSocialService;
-import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
-import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
-import cn.iocoder.yudao.framework.security.core.LoginUser;
-import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
-import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthLoginReqVO;
 import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogCreateReqVO;
 import cn.iocoder.yudao.adminserver.modules.system.convert.auth.SysAuthConvert;
+import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.social.SysSocialUserDO;
 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserDO;
 import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginLogTypeEnum;
 import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginResultEnum;
@@ -21,8 +15,13 @@ import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysUserSessionSe
 import cn.iocoder.yudao.adminserver.modules.system.service.common.SysCaptchaService;
 import cn.iocoder.yudao.adminserver.modules.system.service.logger.SysLoginLogService;
 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
+import cn.iocoder.yudao.adminserver.modules.system.service.social.SysSocialService;
 import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
+import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
 import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
+import cn.iocoder.yudao.framework.security.core.LoginUser;
 import lombok.extern.slf4j.Slf4j;
 import me.zhyd.oauth.model.AuthUser;
 import org.springframework.context.annotation.Lazy;
@@ -41,8 +40,8 @@ import javax.annotation.Resource;
 import java.util.List;
 import java.util.Set;
 
-import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.*;
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static java.util.Collections.singleton;
 
 /**
@@ -71,9 +70,6 @@ public class SysAuthServiceImpl implements SysAuthService {
     @Resource
     private SysSocialService socialService;
 
-    @Resource
-    private SysSocialUserMapper socialUserMapper;
-
     @Override
     public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
         // 获取 username 对应的 SysUserDO
@@ -92,6 +88,8 @@ public class SysAuthServiceImpl implements SysAuthService {
         if (user == null) {
             throw new UsernameNotFoundException(String.valueOf(userId));
         }
+        this.createLoginLog(user.getUsername(), SysLoginLogTypeEnum.LOGIN_MOCK, SysLoginResultEnum.SUCCESS);
+
         // 创建 LoginUser 对象
         LoginUser loginUser = SysAuthConvert.INSTANCE.convert(user);
         loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表
@@ -112,24 +110,26 @@ public class SysAuthServiceImpl implements SysAuthService {
     }
 
     private void verifyCaptcha(String username, String captchaUUID, String captchaCode) {
+        final SysLoginLogTypeEnum logTypeEnum = SysLoginLogTypeEnum.LOGIN_USERNAME;
         String code = captchaService.getCaptchaCode(captchaUUID);
         // 验证码不存在
         if (code == null) {
             // 创建登陆失败日志(验证码不存在)
-            this.createLoginLog(username, SysLoginResultEnum.CAPTCHA_NOT_FOUND);
-            throw ServiceExceptionUtil.exception(AUTH_LOGIN_CAPTCHA_NOT_FOUND);
+            this.createLoginLog(username, logTypeEnum, SysLoginResultEnum.CAPTCHA_NOT_FOUND);
+            throw exception(AUTH_LOGIN_CAPTCHA_NOT_FOUND);
         }
         // 验证码不正确
         if (!code.equals(captchaCode)) {
             // 创建登陆失败日志(验证码不正确)
-            this.createLoginLog(username, SysLoginResultEnum.CAPTCHA_CODE_ERROR);
-            throw ServiceExceptionUtil.exception(AUTH_LOGIN_CAPTCHA_CODE_ERROR);
+            this.createLoginLog(username, logTypeEnum, SysLoginResultEnum.CAPTCHA_CODE_ERROR);
+            throw exception(AUTH_LOGIN_CAPTCHA_CODE_ERROR);
         }
         // 正确,所以要删除下验证码
         captchaService.deleteCaptchaCode(captchaUUID);
     }
 
     private LoginUser login0(String username, String password) {
+        final SysLoginLogTypeEnum logTypeEnum = SysLoginLogTypeEnum.LOGIN_USERNAME;
         // 用户验证
         Authentication authentication;
         try {
@@ -137,25 +137,25 @@ public class SysAuthServiceImpl implements SysAuthService {
             // 在其内部,会调用到 loadUserByUsername 方法,获取 User 信息
             authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
         } catch (BadCredentialsException badCredentialsException) {
-            this.createLoginLog(username, SysLoginResultEnum.BAD_CREDENTIALS);
+            this.createLoginLog(username, logTypeEnum, SysLoginResultEnum.BAD_CREDENTIALS);
             throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
         } catch (DisabledException disabledException) {
-            this.createLoginLog(username, SysLoginResultEnum.USER_DISABLED);
+            this.createLoginLog(username, logTypeEnum, SysLoginResultEnum.USER_DISABLED);
             throw exception(AUTH_LOGIN_USER_DISABLED);
         } catch (AuthenticationException authenticationException) {
             log.error("[login0][username({}) 发生未知异常]", username, authenticationException);
-            this.createLoginLog(username, SysLoginResultEnum.UNKNOWN_ERROR);
+            this.createLoginLog(username, logTypeEnum, SysLoginResultEnum.UNKNOWN_ERROR);
             throw exception(AUTH_LOGIN_FAIL_UNKNOWN);
         }
-        // 登陆成功
+        // 登陆成功的日志
         Assert.notNull(authentication.getPrincipal(), "Principal 不会为空");
-        this.createLoginLog(username, SysLoginResultEnum.SUCCESS);
+        this.createLoginLog(username, logTypeEnum, SysLoginResultEnum.SUCCESS);
         return (LoginUser) authentication.getPrincipal();
     }
 
-    private void createLoginLog(String username, SysLoginResultEnum loginResult) {
+    private void createLoginLog(String username, SysLoginLogTypeEnum logTypeEnum, SysLoginResultEnum loginResult) {
         SysLoginLogCreateReqVO reqVO = new SysLoginLogCreateReqVO();
-        reqVO.setLogType(SysLoginLogTypeEnum.LOGIN_USERNAME.getType());
+        reqVO.setLogType(logTypeEnum.getType());
         reqVO.setTraceId(TracerUtils.getTraceId());
         reqVO.setUsername(username);
         reqVO.setUserAgent(ServletUtils.getUserAgent());
@@ -187,11 +187,14 @@ public class SysAuthServiceImpl implements SysAuthService {
             throw exception(AUTH_THIRD_LOGIN_NOT_BIND);
         }
 
-        // 使用账号密码,进行登陆。
+        // 自动登陆
         SysUserDO user = userService.getUser(socialUsers.get(0).getUserId());
         if (user == null) {
             throw exception(USER_NOT_EXISTS);
         }
+        this.createLoginLog(user.getUsername(), SysLoginLogTypeEnum.LOGIN_SOCIAL, SysLoginResultEnum.SUCCESS);
+
+        // 创建 LoginUser 对象
         LoginUser loginUser = SysAuthConvert.INSTANCE.convert(user);
         // TODO 芋艿:需要改造下,增加各种登陆方式
         loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表
@@ -210,7 +213,7 @@ public class SysAuthServiceImpl implements SysAuthService {
         Assert.notNull(authUser, "授权用户不为空");
 
         // 使用账号密码,进行登陆。
-        LoginUser loginUser = this.login0(reqVO.getUsername(), reqVO.getPassword()); // TODO 芋艿:需要改造下,增加各种登陆方式
+        LoginUser loginUser = this.login0(reqVO.getUsername(), reqVO.getPassword());
         loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表
 
         // 绑定社交用户(新增)

+ 12 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/logger/impl/SysLoginLogServiceImpl.java

@@ -1,5 +1,8 @@
 package cn.iocoder.yudao.adminserver.modules.system.service.logger.impl;
 
+import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserDO;
+import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
+import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogCreateReqVO;
 import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogExportReqVO;
@@ -21,10 +24,19 @@ public class SysLoginLogServiceImpl implements SysLoginLogService {
 
     @Resource
     private SysLoginLogMapper loginLogMapper;
+    @Resource
+    private SysUserService userService;
 
     @Override
     public void createLoginLog(SysLoginLogCreateReqVO reqVO) {
         SysLoginLogDO loginLog = SysLoginLogConvert.INSTANCE.convert(reqVO);
+        // 获得用户
+        SysUserDO user = userService.getUserByUsername(reqVO.getUsername());
+        if (user != null) {
+            loginLog.setUserId(user.getId());
+        }
+        loginLog.setUserType(UserTypeEnum.ADMIN.getValue());
+        // 插入
         loginLogMapper.insert(loginLog);
     }
 

+ 1 - 0
yudao-admin-ui/src/utils/dict.js

@@ -15,6 +15,7 @@ export const DICT_TYPE = {
   SYS_USER_SEX: 'sys_user_sex',
   SYS_NOTICE_TYPE: 'sys_notice_type',
   SYS_OPERATE_TYPE: 'sys_operate_type',
+  SYS_LOGIN_TYPE: 'sys_login_type',
   SYS_LOGIN_RESULT: 'sys_login_result',
   SYS_CONFIG_TYPE: 'sys_config_type',
   SYS_SMS_CHANNEL_CODE: 'sys_sms_channel_code',

+ 1 - 1
yudao-admin-ui/src/views/system/loginlog/index.vue

@@ -37,7 +37,7 @@
       <el-table-column label="访问编号" align="center" prop="id" />
       <el-table-column label="日志类型" align="center" prop="logType">
         <template slot-scope="scope">
-          <span>{{ scope.row.logType === 100 ? '登录' : '退出' }}</span>
+          <span>{{ getDictDataLabel(DICT_TYPE.SYS_LOGIN_TYPE, scope.row.logType) }}</span>
         </template>
       </el-table-column>
       <el-table-column label="用户名称" align="center" prop="username" />

+ 5 - 26
yudao-admin-ui/src/views/system/session/index.vue

@@ -2,22 +2,10 @@
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" label-width="68px">
       <el-form-item label="登录地址" prop="userIp">
-        <el-input
-          v-model="queryParams.userIp"
-          placeholder="请输入登录地址"
-          clearable
-          size="small"
-          @keyup.enter.native="handleQuery"
-        />
+        <el-input v-model="queryParams.userIp" placeholder="请输入登录地址" clearable size="small" @keyup.enter.native="handleQuery"/>
       </el-form-item>
       <el-form-item label="用户名称" prop="username">
-        <el-input
-          v-model="queryParams.username"
-          placeholder="请输入用户名称"
-          clearable
-          size="small"
-          @keyup.enter.native="handleQuery"
-        />
+        <el-input v-model="queryParams.username" placeholder="请输入用户名称" clearable size="small" @keyup.enter.native="handleQuery"/>
       </el-form-item>
       <el-form-item>
         <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
@@ -25,11 +13,7 @@
       </el-form-item>
 
     </el-form>
-    <el-table
-      v-loading="loading"
-      :data="list"
-      style="width: 100%;"
-    >
+    <el-table v-loading="loading" :data="list" style="width: 100%;">
       <el-table-column label="会话编号" align="center" prop="id" width="300" />
       <el-table-column label="登录名称" align="center" prop="username" width="100" />
       <el-table-column label="部门名称" align="center" prop="deptName" width="100" />
@@ -42,13 +26,8 @@
       </el-table-column>
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
         <template slot-scope="scope">
-          <el-button
-            size="mini"
-            type="text"
-            icon="el-icon-delete"
-            @click="handleForceLogout(scope.row)"
-            v-hasPermi="['system:user-session:delete']"
-          >强退</el-button>
+          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleForceLogout(scope.row)"
+            v-hasPermi="['system:user-session:delete']">强退</el-button>
         </template>
       </el-table-column>
     </el-table>