审计日志注解 1、针对增删改接口进行可视化日志审查
2、过滤敏感字段
package com.bytello.customizer.aspect; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.support.spring.PropertyPreFilters; import com.bytello.customizer.common.annotation.Log; import com.bytello.customizer.common.enums.Op; import com.bytello.customizer.common.pojo.entity.SysOpLogDo; import com.bytello.customizer.common.pojo.entity.UserDo; import com.bytello.customizer.common.utils.FastJsonUtil; import com.bytello.customizer.common.utils.ServletUtil; import com.bytello.customizer.holder.UserHolder; import com.bytello.customizer.manager.AsyncManager; import com.bytello.customizer.manager.factory.AsyncFactory; import org.apache.commons.lang3.StringUtils; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import org.springframework.validation.BindingResult; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.Map; /** * 操作日志记录 * * @author wuqinhong * @email wuqinhong@cvte.com * @date 2022-11-14 09:34:45 */ @Aspect @Component public class LogAspect { private static final Logger log = LoggerFactory.getLogger(LogAspect.class); /** * 排除敏感属性字段 */ public static final String[] EXCLUDE_PROPERTIES = {"password", "oldPassword", "newPassword", "confirmPassword"}; // 配置织入点 @Pointcut("@annotation(com.bytello.customizer.common.annotation.Log)") public void logPointCut() { } /** * 处理完请求后执行 * * @param joinPoint 切点 */ @AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult") public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult) { handleLog(joinPoint, controllerLog, null, jsonResult); } /** * 拦截异常操作 * * @param joinPoint 切点 * @param e 异常 */ @AfterThrowing(value = "@annotation(controllerLog)", throwing = "e") public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e) { handleLog(joinPoint, controllerLog, e, null); } protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult) { try { // 获取当前的用户 UserDo currentUser = UserHolder.get(); // *========数据库日志=========*// SysOpLogDo opLog = new SysOpLogDo(); opLog.setStatus(Op.Status.SUCCESS.ordinal()); // 请求的地址 HttpServletRequest req = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); String ip = req.getRemoteAddr(); opLog.setOpIp(ip); // 操作时间 opLog.setOpTime(new Date()); // 请求地址 opLog.setOpUrl(StringUtils.substring(ServletUtil.getRequest().getRequestURI(), 0, 255)); if (currentUser != null) { opLog.setOpName(currentUser.getAccount()); } // 获取异常信息 if (e != null) { opLog.setStatus(Op.Status.FAIL.ordinal()); opLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000)); } // 设置方法名称 String className = joinPoint.getTarget().getClass().getName(); String methodName = joinPoint.getSignature().getName(); opLog.setMethod(className + "." + methodName + "()"); // 设置请求方式 opLog.setRequestMethod(ServletUtil.getRequest().getMethod()); // 处理设置注解上的参数 getControllerMethodDescription(joinPoint, controllerLog, opLog, jsonResult); // 保存数据库 AsyncManager.instance().execute(AsyncFactory.recordOp(opLog)); } catch (Exception exp) { // 记录本地异常日志 log.error("==前置通知异常=="); log.error("异常信息:{}", exp.getMessage()); exp.printStackTrace(); } } /** * 获取注解中对方法的描述信息 用于Controller层注解 * * @param log 日志 * @param opLog 操作日志 * @throws Exception */ public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysOpLogDo opLog, Object jsonResult) throws Exception { // 设置标题 opLog.setTitle(log.title()); //设置操作类型 opLog.setOpType(log.opType().ordinal()); // 是否需要保存request,参数和值 if (log.isSaveRequestData()) { // 获取参数的信息,传入到数据库中。 //setRequestValue(joinPoint, opLog); setRequestBody(opLog); } // 是否需要保存response,参数和值 if (log.isSaveResponseData() && jsonResult != null) { opLog.setJsonResult(StringUtils.substring(JSONObject.toJSONString(jsonResult), 0, 2000)); } } /** * 获取请求体,放到log中 * * @param opLog */ private void setRequestBody(SysOpLogDo opLog){ String requestJson = ServletUtil.getRequestBody(); //过滤敏感属性 HashMap<String, String> map = FastJsonUtil.json2Map(requestJson); String filtered = JSONObject.toJSONString(map, excludePropertyPreFilter()); opLog.setOpParam(filtered); } /** * 忽略敏感属性 */ public PropertyPreFilters.MySimplePropertyPreFilter excludePropertyPreFilter() { return new PropertyPreFilters().addFilter().addExcludes(EXCLUDE_PROPERTIES); } }