日志审计功能实现

2023-11-09

1. 前言

日志审计功能就是将用户进行的增加、修改和删除操作内容、操作方法、操作人以及操作时间等统一格式后集中放入数据库存储,这样做是为了提高系统的安全性,方便系统发生事故后的溯源和恢复。

2. 日志审计实现

2.1 设计数据库

 下图为数据库中的结构:
在这里插入图片描述

2.2 自定义注解

 这里我们需要自己设计一个注解,作为AOP的切点,当执行被注解标记的方法时,则会进入AOP切面执行日志入库的操作。

 示例如下:

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import java.lang.annotation.*;

@Target(ElementType.METHOD) //注解放置的目标位置,METHOD是可注解在方法级别上
@Retention(RetentionPolicy.RUNTIME) //注解在哪个阶段执行
@Documented
public @interface LogRecord {
    String module() default ""; // 操作模块
    String type() default "";  // 操作类型
    String desc() default "";  // 操作说明
    Class mapperClass() default BaseMapper.class; // 服务类
}

2.3 设计获取IOC容器的工具类

 具体IOC容器获取的方法请参考我的上一篇博客:Springboot获取IOC容器的方式

 示例如下:

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class SpringContextUtil implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    public SpringContextUtil() {
    }

    /**
     * 设置上下文
     * @param applicationContext
     * @throws BeansException
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (SpringContextUtil.applicationContext == null) {
            SpringContextUtil.applicationContext = applicationContext;
        }

    }

    /**
     * 获取上下文
     * @return
     */
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    /**
     * 通过名字获取上下文中的bean
     * @param name
     * @return
     */
    public static Object getBean(String name){
        return applicationContext.getBean(name);
    }

    /**
     * 通过类型获取上下文中的bean
     * @param requiredType
     * @return
     */
    public static Object getBean(Class<?> requiredType){
        return applicationContext.getBean(requiredType);
    }
}

2.4 标记需要审计的方法

 我们选择将LogRecord注解标注在Service层的方法上,只要Service层被标注的方法执行就会进行日志审计并入库。

 示例如下:

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class TestServiceImpl implements TestService {
    @Autowired
    private TestMapper testMapper;

    /**
     * 根据id修改testEntity中的数据
     * @param testEntity 测试用的实体类
     * @return
     */
    @LogRecord(module = "测试模块", type = "修改", desc = "根据testEntity中的id修改数据", mapperClass = TestMapper.class)
    public boolean updateTest(TestEntity testEntity) {
        int result = 0;
        try {
            result = testMapper.updateById(testEntity);
        } catch (Exception e) {
            log.error("updateTest insert error:{}", e.toString());
        }

        return result > 0;
    }
}

2.5 使用AOP将操作记录入库

 最后,我们只需要利用前面铺垫的IOC容器即可实现入库操作。

 示例如下:

import com.google.gson.Gson;
import com.jd.jdt.kg.domain.entity.OperLog;
import com.jd.jdt.kg.service.context.SpringContextUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.lang.reflect.Method;

@Aspect
@Component
@Slf4j
public class ValidationAspect {

    @Autowired
    private LogAuditMapper logAuditMapper;      // 用于向日志审计库中存放数据

    @Pointcut("@annotation(com.guyan.entity.LogRecord)")
    public void logRecordPointCut() {
    }

    @AfterReturning(value = "logRecordPointCut()", returning = "result")
    public void afterReturning(ProceedingJoinPoint joinPoint, Object result) throws Throwable {
        log.info("logRecord after begin!");
        // 获取方法签名
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        OperLog operLog = method.getAnnotation(OperLog.class);
        // 用于json格式转换
        Gson gson = new Gson();
        // Mapper层类类
        Class mapperClass = operLog.mapperClass();
        // mapper层实例名
        String simpleNameToLower = mapperClass.getSimpleName().substring(0,1).toLowerCase().concat(mapperClass.getSimpleName().substring(1));
        // 从Spring的容器中获取实例
        Object instance = SpringContextUtil.getApplicationContext().getBean(simpleNameToLower);
        // 获取到要执行的方法
        Method selectById = mapperClass.getMethod("selectById", Serializable.class);
        // 类名
        String className = joinPoint.getTarget().getClass().getName();
        // 方法名
        String methodName = method.getName();
        // 创建日志实体
        LogAuditEntity logAuditEntity = new LogAuditEntity();
        logAuditEntity.setMethod(className + "." + methodName);
        logAuditEntity.setMethodReq(gson.toJson(joinPoint.getArgs()));
        logAuditEntity.setModule(operLog.operModule());
        logAuditEntity.setType(operLog.operType());
        logAuditEntity.setDesc(operLog.operDesc());
        // 根据方法返回值截取id值
        Long id = getIdByReturn(result);
        Object invoke = selectById.invoke(instance, id);
        if (invoke == null) {
            invoke = "";
        }
        logAuditEntity.setReturn(gson.toJson(invoke));

        try {
            logAuditMapper.insert(operLogEntity);
        } catch (Throwable e) {
            log.error("logRecord Around error:{}", gson.toJson(e));
        }

        log.info("logRecord after end!");
    }

    /**
     * 根据方法返回值截取id
     * @param result
     * @return
     */
    private Long getIdByReturn(Object result) {
        Long id = null;
        // 由于每个人的方法返回值结构不同,故此方法体内容根据返回值结构自己更改
        return id;
    }
}

 大家可以根据自己需求自定义getIdByReturn方法、LogAuditMapper类和LogAuditEntity类。

3. 结尾

都看到最后了,求求大家点个赞再走吧!你的支持是博主创作的最大动力。

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

日志审计功能实现 的相关文章

随机推荐

  • CMake:递归检查并拷贝所有需要的DLL文件

    文章目录 1 目的 2 设计 整体思路 多层依赖的处理 获取 DLL 所在目录 探测剩余的 DLL 文件 3 代码实现 判断 stack 是否为空 判断 stack 是否为空 获取所有 target 检测并拷贝 DLL 4 使用 1 目的
  • 苏州吴江区实现首单跨区域数字人民币试点场景应用

    作为数字人民币试点的首批城市 苏州一直在数字人民币应用场景的落地方面进展迅速 其中 苏州相城区在全市率先开展数字人民币场景建设及试点 截至目前 已开放试点场景7500余个 占全市总数近50 并在全国率先落地交通补贴批量代发 房屋契税缴纳 智
  • python num循环怎么从1开始

    如何实现python for循环从1开始 range 函数的作用和用法 编写一个从数值1开始的循环 执行后得到的结果 其他注意事项
  • 在OTFS学习中的一些总结

    双选特性 多径传播 gt 时延 gt 频率选择性 时延的倒数为相干带宽 在频域内信道相应的幅值大概保持不变的一段频率称为相干带宽 当信号的带宽小于相干带宽 或者说信号的传输时间 周期 大于时延拓展 信号之间没有干扰 我们认为信号是没有失真的
  • Win10下Anaconda使用conda activate激活环境出错

    直接输入conda activate pytorch 报如下错误 解决方法 1 在base路径下先输入activate 提示如下 2 再输入conda activate base 激活base环境 3 在输入conda activate p
  • [python知识] 爬虫知识之BeautifulSoup库安装及简单介绍

    一 前言 在前面的几篇文章中我介绍了如何通过Python分析源代码来爬取博客 维基百科InfoBox和图片 其文章链接如下 python学习 简单爬取维基百科程序语言消息盒 Python学习 简单网络爬虫抓取博客文章及思想介绍 python
  • awk使用shell变量,shell获取awk中的变量值

    awk使用shell变量 shell获取awk中的变量值 2012 04 13 09 36 28 分类 LINUX 字号 订阅 原文 http renyongjie668 blog 163 com blog static 160053120
  • 今天面试招了个18K的人,从腾讯出来的果然都有两把刷子···

    公司前段时间缺人 也面了不少测试 前面一开始瞄准的就是中级的水准 也没指望来大牛 提供的薪资在15 20k 面试的人很多 但平均水平很让人失望 看简历很多都是4年工作经验 但面试中 不提测试工具 仅仅基础的技术很多也知之不详 多数人数年的工
  • Android 系统启动流程简介

    1 Init 进程启动流程 2 Zygote启动流程 3 SystemServer启动流程 1 Init 进程启动流程 Android启动流程 init进程 gt Zygote进程 gt SystemServer进程 gt 各种应用进程 I
  • [源码解析] NVIDIA HugeCTR,GPU 版本参数服务器---(7) ---Distributed Hash之前向传播

    Python微信订餐小程序课程视频 https edu csdn net course detail 36074 Python实战量化交易理财系统 https edu csdn net course detail 35475 源码解析 NV
  • 【Php】PhpSpreadsheet安装的坑怎么这么多!

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 人是代码非 一 PhpSpreadsheet不安装直接用行不行 二 安装的坑 1 缺少fileinfo扩展 2 下载中断 3 proc open函数被禁用 4 co
  • Jmeter 集合点详细讲解

    集合点 让所有请求在不满足条件的时候处于等待状态 如 我集合点设置为50 那么不满足50个请求的时候 这些请求都会集合在一起 处于等待状态 当达到50的时候 就一起执行 从而达到并发的效果 那么Jmeter中可以通过同步定时器Synchro
  • Mybatis

    最近又遇到mybatis的问题了 所以把之前写的和补充的笔记一起放上来 一 动态sql 在编写项目的时候经常需要拼接一些复杂的SQL语句 而拼接过程中很容易导致错误 而Mybatis的动态SQL功能正好能够解决这种问题 可以通过使用 if
  • 【长文预警】美团联合创始人王慧文清华产品课

    前言 一 成功和失败的产品 一般来说在一个领域里一款产品的成功对应着无数产品的失败 根据老王个人的经验 成功和失败的比例大约是1 30 失败的原因多种多样 有些啥都没做对 有些作对了一部分 这里列举的失败案例主要讲做对了一部分的 准确说算是
  • sonar.java.binaries的配置

    从sonarQube 4 12开始 sonar将会进行程序的动态检查 不配置sonar java binaries属性将会出错 From SonarJava version 4 12 binary files are required fo
  • 在 Mac 上使用 VMware 安装 Windows 11

    因为项目原因 需要在 windows 环境下测试一下 electron 的表现 于是就记录一下在 mac 虚拟机上安装 windows 的体验 总体来说难度不大 我电脑的情况 2020 款 macbook pro 16g 512g 前期准备
  • golang版本管理gvm

    今天小土带来一篇关于Go版本管理器gvm的小短文 废话不多说 开始安装 安装 如果你使用的mac mac 需要先安装xcode select 没安装过的同学可以按照如下命令进行执行安装 这里不做太多说明了 xcode select inst
  • 地震逃生【最大流模板题】

    题目链接 P1343 地震逃生 简单的最大流的模板 小心 0 的RE情况 读题 另外 写的是ISAP include
  • 微信小程序授权登录页面(有提示窗)

    微信小程序授权登录 有弹窗提示 1 效果显示 1 1 授权登录页面 1 2 授权登录提示弹窗 1 3 拒绝授权登录 1 4 允许登录后 跳转到小程序首页 2 代码 2 1 wxml 文件
  • 日志审计功能实现

    1 前言 日志审计功能就是将用户进行的增加 修改和删除操作内容 操作方法 操作人以及操作时间等统一格式后集中放入数据库存储 这样做是为了提高系统的安全性 方便系统发生事故后的溯源和恢复 2 日志审计实现 2 1 设计数据库 下图为数据库中的