:zip: 将登陆日志从操作日志中剥离开来,方便后续扩展

This commit is contained in:
b2baccline
2020-09-17 18:12:24 +08:00
parent 5c5614c910
commit f6826bf561
13 changed files with 476 additions and 65 deletions

View File

@@ -0,0 +1,26 @@
package com.hccake.ballcat.admin.constants;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 登陆事件
* @author Hccake 2020/9/17
* @version 1.0
*/
@Getter
@AllArgsConstructor
public enum LoginEventTypeEnum {
/**
* 登录
*/
LOGIN(1),
/**
* 登出
*/
LOGOUT(2);
private final int value;
}

View File

@@ -11,7 +11,6 @@ import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -33,7 +32,7 @@ public class AdminAccessLogController {
* 分页查询
* @param page 分页对象
* @param adminAccessLog 访问日志
* @return
* @return R
*/
@ApiOperation(value = "分页查询", notes = "分页查询")
@GetMapping("/page")
@@ -42,16 +41,4 @@ public class AdminAccessLogController {
return R.ok(adminAccessLogService.page(page, Wrappers.query(adminAccessLog)));
}
/**
* 通过id查询访问日志
* @param id id
* @return R
*/
@ApiOperation(value = "通过id查询后台访问日志", notes = "通过id查询后台访问日志")
@GetMapping("/{id}")
@PreAuthorize("@per.hasPermission('log:adminaccesslog:read')")
public R<AdminAccessLog> getById(@PathVariable("id") Long id) {
return R.ok(adminAccessLogService.getById(id));
}
}

View File

@@ -0,0 +1,43 @@
package com.hccake.ballcat.admin.modules.log.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hccake.ballcat.admin.modules.log.model.qo.AdminLoginLogQO;
import com.hccake.ballcat.admin.modules.log.model.vo.AdminLoginLogVO;
import com.hccake.ballcat.admin.modules.log.service.AdminLoginLogService;
import com.hccake.ballcat.common.core.result.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 登陆日志
*
* @author hccake 2020-09-16 20:21:10
*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/log/adminloginlog")
@Api(value = "adminloginlog", tags = "登陆日志管理")
public class AdminLoginLogController {
private final AdminLoginLogService AdminLoginLogService;
/**
* 分页查询
* @param page 分页对象
* @param adminLoginLogQO 登陆日志查询对象
* @return R 通用返回体
*/
@ApiOperation(value = "分页查询", notes = "分页查询")
@GetMapping("/page")
@PreAuthorize("@per.hasPermission('log:adminloginlog:read')")
public R<IPage<AdminLoginLogVO>> getLoginLogPage(Page<?> page, AdminLoginLogQO adminLoginLogQO) {
return R.ok(AdminLoginLogService.selectPageVo(page, adminLoginLogQO));
}
}

View File

@@ -11,7 +11,6 @@ import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -33,7 +32,7 @@ public class AdminOperationLogController {
* 分页查询
* @param page 分页对象
* @param adminOperationLog 操作日志
* @return
* @return R
*/
@ApiOperation(value = "分页查询", notes = "分页查询")
@GetMapping("/page")
@@ -43,16 +42,4 @@ public class AdminOperationLogController {
return R.ok(operationLogAdminService.page(page, Wrappers.query(adminOperationLog)));
}
/**
* 通过id查询操作日志
* @param id id
* @return R
*/
@ApiOperation(value = "通过id查询", notes = "通过id查询")
@GetMapping("/{id}")
@PreAuthorize("@per.hasPermission('log:adminoperationlog:read')")
public R<AdminOperationLog> getById(@PathVariable("id") Long id) {
return R.ok(operationLogAdminService.getById(id));
}
}

View File

@@ -0,0 +1,26 @@
package com.hccake.ballcat.admin.modules.log.mapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.hccake.ballcat.admin.modules.log.model.entity.AdminLoginLog;
import com.hccake.ballcat.admin.modules.log.model.vo.AdminLoginLogVO;
import org.apache.ibatis.annotations.Param;
/**
* 登陆日志
*
* @author hccake 2020-09-16 20:21:10
*/
public interface AdminLoginLogMapper extends BaseMapper<AdminLoginLog> {
/**
* 分页查询
* @param page 分页对象
* @param wrapper 查询wrapper
* @return IPage<LoginLogVO> VO分页数据
*/
IPage<AdminLoginLogVO> selectPageVo(IPage<?> page, @Param(Constants.WRAPPER) Wrapper<AdminLoginLog> wrapper);
}

View File

@@ -0,0 +1,103 @@
package com.hccake.ballcat.admin.modules.log.model.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.hccake.ballcat.admin.constants.LoginEventTypeEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.time.LocalDateTime;
/**
* 登陆日志
*
* @author hccake 2020-09-16 20:21:10
*/
@Data
@Accessors(chain = true)
@TableName("admin_login_log")
@ApiModel(value = "登陆日志")
public class AdminLoginLog {
private static final long serialVersionUID = 1L;
/**
* 编号
*/
@TableId
@ApiModelProperty(value = "编号")
private Long id;
/**
* 追踪ID
*/
@ApiModelProperty(value = "追踪ID")
private String traceId;
/**
* 用户名
*/
@ApiModelProperty(value = "用户名")
private String username;
/**
* 操作信息
*/
@ApiModelProperty(value = "登陆IP")
private String ip;
/**
* 操作系统
*/
@ApiModelProperty(value = "操作系统")
private String os;
/**
* 状态
*/
@ApiModelProperty(value = "状态")
private Integer status;
/**
* 日志消息
*/
@ApiModelProperty(value = "日志消息")
private String msg;
/**
* 登陆地点 TODO IP解析工具暂时未定 IP解析工具类需要简单封装下方便替换底层工具
*/
@ApiModelProperty(value = "登陆地点")
private String location;
/**
* 事件类型 登陆/登出
* @see LoginEventTypeEnum
*/
@ApiModelProperty(value = "事件类型")
private Integer eventType;
/**
* 浏览器
*/
@ApiModelProperty(value = "浏览器")
private String browser;
/**
* 登录/登出时间
*/
@ApiModelProperty(value = "登录/登出时间")
private LocalDateTime loginTime;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
@ApiModelProperty(value = "创建时间")
private LocalDateTime createTime;
}

View File

@@ -0,0 +1,68 @@
package com.hccake.ballcat.admin.modules.log.model.qo;
import cn.hutool.core.date.DatePattern;
import com.hccake.ballcat.admin.constants.LoginEventTypeEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
/**
* 登陆日志 查询对象
*
* @author hccake 2020-09-16 20:21:10
*/
@Data
@ApiModel(value = "登陆日志查询对象")
public class AdminLoginLogQO {
private static final long serialVersionUID = 1L;
/**
* 追踪ID
*/
@ApiModelProperty(value = "追踪ID")
private String traceId;
/**
* 用户名
*/
@ApiModelProperty(value = "用户名")
private String username;
/**
* 操作信息
*/
@ApiModelProperty(value = "操作信息")
private String ip;
/**
* 状态
*/
@ApiModelProperty(value = "状态")
private Integer status;
/**
* 事件类型 登陆/登出
* @see LoginEventTypeEnum
*/
@ApiModelProperty(value = "事件类型")
private Integer eventType;
/**
* 登陆时间区间(开始时间)
*/
@DateTimeFormat(pattern = DatePattern.NORM_DATETIME_PATTERN)
@ApiModelProperty(value = "开始时间(登陆时间区间)")
private LocalDateTime startTime;
/**
* 登陆时间区间(结束时间)
*/
@DateTimeFormat(pattern = DatePattern.NORM_DATETIME_PATTERN)
@ApiModelProperty(value = "结束时间(登陆时间区间)")
private LocalDateTime endTime;
}

View File

@@ -0,0 +1,94 @@
package com.hccake.ballcat.admin.modules.log.model.vo;
import com.hccake.ballcat.admin.constants.LoginEventTypeEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 登陆日志
*
* @author hccake 2020-09-16 20:21:10
*/
@Data
@ApiModel(value = "登陆日志")
public class AdminLoginLogVO {
private static final long serialVersionUID = 1L;
/**
* 编号
*/
@ApiModelProperty(value = "编号")
private Long id;
/**
* 追踪ID
*/
@ApiModelProperty(value = "追踪ID")
private String traceId;
/**
* 用户名
*/
@ApiModelProperty(value = "用户名")
private String username;
/**
* 操作信息
*/
@ApiModelProperty(value = "操作信息")
private String ip;
/**
* 操作系统
*/
@ApiModelProperty(value = "操作系统")
private String os;
/**
* 状态
*/
@ApiModelProperty(value = "状态")
private Integer status;
/**
* 日志消息
*/
@ApiModelProperty(value = "日志消息")
private String msg;
/**
* 登陆地点
*/
@ApiModelProperty(value = "登陆地点")
private String location;
/**
* 事件类型 登陆/登出
* @see LoginEventTypeEnum
*/
@ApiModelProperty(value = "事件类型")
private Integer eventType;
/**
* 浏览器
*/
@ApiModelProperty(value = "浏览器")
private String browser;
/**
* 登录/登出时间
*/
@ApiModelProperty(value = "登录/登出时间")
private LocalDateTime loginTime;
/**
* 创建时间
*/
@ApiModelProperty(value = "创建时间")
private LocalDateTime createTime;
}

View File

@@ -0,0 +1,24 @@
package com.hccake.ballcat.admin.modules.log.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.hccake.ballcat.admin.modules.log.model.entity.AdminLoginLog;
import com.hccake.ballcat.admin.modules.log.model.vo.AdminLoginLogVO;
import com.hccake.ballcat.admin.modules.log.model.qo.AdminLoginLogQO;
/**
* 登陆日志
*
* @author hccake 2020-09-16 20:21:10
*/
public interface AdminLoginLogService extends IService<AdminLoginLog> {
/**
* 根据QueryObject查询分页数据
* @param page 分页参数
* @param qo 查询参数对象
* @return IPage<LoginLogVO> 分页数据
*/
IPage<AdminLoginLogVO> selectPageVo(IPage<?> page, AdminLoginLogQO qo);
}

View File

@@ -0,0 +1,46 @@
package com.hccake.ballcat.admin.modules.log.service.impl;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hccake.ballcat.admin.modules.log.mapper.AdminLoginLogMapper;
import com.hccake.ballcat.admin.modules.log.model.entity.AdminLoginLog;
import com.hccake.ballcat.admin.modules.log.model.qo.AdminLoginLogQO;
import com.hccake.ballcat.admin.modules.log.model.vo.AdminLoginLogVO;
import com.hccake.ballcat.admin.modules.log.service.AdminLoginLogService;
import org.springframework.stereotype.Service;
/**
* 登陆日志
*
* @author hccake 2020-09-16 20:21:10
*/
@Service
public class AdminAdminLoginLogServiceImpl extends ServiceImpl<AdminLoginLogMapper, AdminLoginLog>
implements AdminLoginLogService {
private final static String TABLE_ALIAS_PREFIX = "ll.";
/**
* 根据QueryObject查询分页数据
* @param page 分页参数
* @param qo 查询参数对象
* @return IPage<LoginLogVO> 分页数据
*/
@Override
public IPage<AdminLoginLogVO> selectPageVo(IPage<?> page, AdminLoginLogQO qo) {
QueryWrapper<AdminLoginLog> wrapper = Wrappers.<AdminLoginLog>query()
.eq(StrUtil.isNotBlank(qo.getUsername()), TABLE_ALIAS_PREFIX + "username", qo.getUsername())
.eq(StrUtil.isNotBlank(qo.getTraceId()), TABLE_ALIAS_PREFIX + "trace_id", qo.getTraceId())
.eq(StrUtil.isNotBlank(qo.getIp()), TABLE_ALIAS_PREFIX + "ip", qo.getIp())
.eq(ObjectUtil.isNotNull(qo.getEventType()), TABLE_ALIAS_PREFIX + "event_type", qo.getEventType())
.eq(ObjectUtil.isNotNull(qo.getStatus()), TABLE_ALIAS_PREFIX + "status", qo.getStatus())
.gt(ObjectUtil.isNotNull(qo.getStartTime()), TABLE_ALIAS_PREFIX + "login_time", qo.getStartTime())
.lt(ObjectUtil.isNotNull(qo.getEndTime()), TABLE_ALIAS_PREFIX + "login_time", qo.getEndTime());
return baseMapper.selectPageVo(page, wrapper);
}
}

View File

@@ -1,12 +1,12 @@
package com.hccake.ballcat.admin.oauth.listener;
import cn.hutool.core.util.URLUtil;
import cn.hutool.json.JSONUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import com.hccake.ballcat.admin.constants.LoginEventTypeEnum;
import com.hccake.ballcat.admin.modules.log.model.entity.AdminLoginLog;
import com.hccake.ballcat.admin.modules.log.service.AdminLoginLogService;
import com.hccake.ballcat.commom.log.constant.LogConstant;
import com.hccake.ballcat.commom.log.operation.enums.LogStatusEnum;
import com.hccake.ballcat.commom.log.operation.enums.OperationTypeEnum;
import com.hccake.ballcat.commom.log.operation.model.OperationLogDTO;
import com.hccake.ballcat.commom.log.operation.service.OperationLogHandler;
import com.hccake.ballcat.commom.log.util.LogUtils;
import com.hccake.ballcat.common.core.util.IPUtil;
import lombok.RequiredArgsConstructor;
@@ -33,7 +33,7 @@ import java.util.HashMap;
@Component
public class LoginEventListener {
private final OperationLogHandler operationLogHandler;
private final AdminLoginLogService adminLoginLogService;
/**
* 登陆成功时间监听 记录用户登录日志
@@ -50,24 +50,22 @@ public class LoginEventListener {
// TODO 暂时只记录了 password 模式,其他的第三方登陆,等 spring-authorization-server 孵化后重构
// https://github.com/spring-projects-experimental/spring-authorization-server
if ("password".equals(((HashMap) details).get("grant_type"))) {
// 记录登陆日志
OperationLogDTO operationLogDTO = prodOperationLogDTO(source).setType(OperationTypeEnum.LOGIN.getValue())
.setMsg("Login Success");
operationLogHandler.saveLog(operationLogDTO);
AdminLoginLog adminLoginLog = prodLoginLog(source).setMsg("登陆成功")
.setStatus(LogStatusEnum.SUCCESS.getValue()).setEventType(LoginEventTypeEnum.LOGIN.getValue());
adminLoginLogService.save(adminLoginLog);
}
}
/**
* On logout success event.
* 监听鉴权失败事件
* @param event the event
*/
@EventListener(AbstractAuthenticationFailureEvent.class)
public void onAuthenticationFailureEvent(AbstractAuthenticationFailureEvent event) {
AbstractAuthenticationToken source = (AbstractAuthenticationToken) event.getSource();
// 记录登出日志
OperationLogDTO operationLogDTO = prodOperationLogDTO(source).setType(OperationTypeEnum.LOGIN.getValue())
.setMsg("Login Error" + event.getException().getMessage()).setStatus(LogStatusEnum.FAIL.getValue());
operationLogHandler.saveLog(operationLogDTO);
AdminLoginLog adminLoginLog = prodLoginLog(source).setMsg(event.getException().getMessage())
.setEventType(LoginEventTypeEnum.LOGIN.getValue()).setStatus(LogStatusEnum.FAIL.getValue());
adminLoginLogService.save(adminLoginLog);
}
/**
@@ -77,25 +75,28 @@ public class LoginEventListener {
@EventListener(LogoutSuccessEvent.class)
public void onLogoutSuccessEvent(LogoutSuccessEvent event) {
AbstractAuthenticationToken source = (AbstractAuthenticationToken) event.getSource();
// 记录登出日志
OperationLogDTO operationLogDTO = prodOperationLogDTO(source).setType(OperationTypeEnum.LOGOUT.getValue())
.setMsg("Logout Success");
operationLogHandler.saveLog(operationLogDTO);
AdminLoginLog adminLoginLog = prodLoginLog(source).setMsg("登出成功")
.setEventType(LoginEventTypeEnum.LOGOUT.getValue());
adminLoginLogService.save(adminLoginLog);
}
/**
* 根据token和请求信息产生一个操作日志
* 根据token和请求信息产生一个登陆日志
* @param source AbstractAuthenticationToken 当前token
* @return OperationLogDTO 操作日志DTO
* @return LoginLog 登陆日志
*/
private OperationLogDTO prodOperationLogDTO(AbstractAuthenticationToken source) {
private AdminLoginLog prodLoginLog(AbstractAuthenticationToken source) {
// 获取 Request
HttpServletRequest request = LogUtils.getHttpServletRequest();
return new OperationLogDTO().setCreateTime(LocalDateTime.now()).setIp(IPUtil.getIpAddr(request))
.setMethod(request.getMethod()).setStatus(LogStatusEnum.SUCCESS.getValue())
.setUserAgent(request.getHeader("user-agent")).setUri(URLUtil.getPath(request.getRequestURI()))
.setTraceId(MDC.get(LogConstant.TRACE_ID)).setParams(JSONUtil.toJsonStr(request.getParameterMap()))
.setTime(0L).setOperator(source.getName());
AdminLoginLog adminLoginLog = new AdminLoginLog().setLoginTime(LocalDateTime.now())
.setIp(IPUtil.getIpAddr(request)).setStatus(LogStatusEnum.SUCCESS.getValue())
.setTraceId(MDC.get(LogConstant.TRACE_ID)).setUsername(source.getName());
// 根据 ua 获取浏览器和操作系统
UserAgent ua = UserAgentUtil.parse(request.getHeader("user-agent"));
if (ua != null) {
adminLoginLog.setBrowser(ua.getBrowser().getName()).setOs(ua.getOs().getName());
}
return adminLoginLog;
}
}

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hccake.ballcat.admin.modules.log.mapper.AdminLoginLogMapper">
<sql id="Base_Alias_Column_List">
ll.id, ll.trace_id, ll.username, ll.ip, ll.os, ll.status, ll.msg, ll.location, ll.browser, ll.event_type, ll.login_time, ll.create_time
</sql>
<select id="selectPageVo" resultType="com.hccake.ballcat.admin.modules.log.model.vo.AdminLoginLogVO">
SELECT
<include refid="Base_Alias_Column_List"/>
FROM
admin_login_log ll
${ew.customSqlSegment}
</select>
</mapper>