当前位置: 首页 > news >正文

Springboot + AOP + 注解做全局日志拦截并且排除敏感属性以及接口相应时间

前言

我们在使用接口的时候需要有日志记录,然后我们也希望一些敏感参数不要出现在我们的日志里面保护用户的隐私

废话不多说我们直接上代码开干

依赖的选择,我们可以直接使用Springboot继承的aop依赖,可以单独导入我们aop依赖织入包
然后我们还需要导入阿里巴巴的fastjson包

<dependency><groupId>com.alibaba.fastjson2</groupId><artifactId>fastjson2</artifactId><version>2.0.29</version>
</dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.6</version>
</dependency>

1、首先我们需要定义一个日志注解

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface SystemLog {/*** 操作的模块*/public String businessType() default "";/*** 排除指定的请求参数*/public String[] excludeParamNames() default {};
}

2、我们需要去定义我们的切面类

/*** description : 操作日志记录处理** @author : 沐光* @date : 2024-08-28*/
@Aspect
@Component
public class LogAspect {private static final Logger logger = LoggerFactory.getLogger(LogAspect.class);// 排除敏感属性字段public static final String[] EXCLUDE_PROPERTIES = { "password", "oldPassword", "newPassword", "confirmPassword", "phoneNumber" };// 计算操作消耗时间private static final ThreadLocal<Long> TIME_THREADLOCAL = new NamedThreadLocal<>("cost time");// 定义切面@Pointcut("@annotation(com.wky.book.common.annotation.SystemLog)")public void pointCut() {}// 处理请求之前@Before( value = "@annotation(systemLog)")public void before(JoinPoint joinPoint, SystemLog systemLog) throws Exception{TIME_THREADLOCAL.set(System.currentTimeMillis());ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = Optional.of(requestAttributes.getRequest()).get();String businessType = systemLog.businessType();logger.info("+++++++++++++++++++++++++++++++++++ Start +++++++++++++++++++++++++++++++++++");// 打印描述信息logger.info("Description    : {}", businessType);// 打印请求 urllogger.info("URL            : {}", request.getRequestURL().toString());// 打印 Http methodlogger.info("HTTP Method    : {}", request.getMethod());// 打印请求的接口以及类型logger.info("request path   : {}", request.getRequestURI());// 打印调用 controller 的全路径以及执行方法logger.info("Class Method   : {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());// 打印请求的 IPlogger.info("IP             : {}", request.getRemoteAddr());// 打印请求入参,我们需要排除掉我们的敏感信息,首先从我们的注解从获取参数logger.info("Request Args   : {}", argsArrayToString(joinPoint.getArgs(), systemLog.excludeParamNames()));}@Around("pointCut()")public Object around(ProceedingJoinPoint point) throws Throwable{Object result = point.proceed();logger.info("Response Args  : {}", JSON.toJSON(result));logger.info("Time-Consuming : {} ms", System.currentTimeMillis() - TIME_THREADLOCAL.get());return result;}/*** description 排除敏感信息,并且返回字符串* @author 沐光* @date 2024/8/28*/private String argsArrayToString(Object[] args, String[] excludeParamNames){String params = "";if (args != null && args.length > 0){for (Object arg : args) {if (!StringUtils.isEmpty(arg) && !isFilterObject(arg)){try{String jsonString = JSON.toJSONString(arg, excludePropertyPreFilter(excludeParamNames));params += jsonString + " ";}catch (Exception e){}}}}return params.trim();}/*** description 忽略敏感属性* @return com.wky.book.common.filter.PropertyPreExcludeFilter* @author 沐光* @date 2024/8/28*/private PropertyPreExcludeFilter excludePropertyPreFilter(String[] excludeParamNames) {return new PropertyPreExcludeFilter().addExcludes(ArrayUtils.addAll(excludeParamNames, EXCLUDE_PROPERTIES));}/*** description 判断这个参数是不是要过滤的,如果是我们返回true* @author 沐光* @date 2024/8/28*/@SuppressWarnings("rawtypes")private boolean isFilterObject(final Object arg){Class<?> clazz = arg.getClass();if (clazz.isArray()){return clazz.getComponentType().isAssignableFrom(MultipartFile.class);}else if (Collection.class.isAssignableFrom(clazz)){Collection collection = (Collection) arg;for (Object value : collection){return value instanceof MultipartFile;}}else if (Map.class.isAssignableFrom(clazz)){Map map = (Map) arg;for (Object value : map.entrySet()){Map.Entry entry = (Map.Entry) value;return entry.getValue() instanceof MultipartFile;}}return arg instanceof MultipartFile || arg instanceof HttpServletRequest || arg instanceof HttpServletResponse || arg instanceof BindingResult;}}

3、最终的我们需要去定义一个我们过滤敏感属性的过滤器

因为我们使用了fastjson里面的一个方法去过滤我们敏感字段,所以我们需要去创建这个过滤器

/*** description : 排除敏感信息** @author : 沐光* @date : 2024-08-28*/
public class PropertyPreExcludeFilter extends SimplePropertyPreFilter
{public PropertyPreExcludeFilter(){}public PropertyPreExcludeFilter addExcludes(String... filters){for (int i = 0; i < filters.length; i++){this.getExcludes().add(filters[i]);}return this;}
}

4、总结

如果大家感兴趣的话可以去看一下fastjson的源码,主要是去看这个一行代码
String jsonString = JSON.toJSONString(arg, excludePropertyPreFilter(excludeParamNames));
里面的这个类方法大家会明白了!!!


http://www.mrgr.cn/news/13859.html

相关文章:

  • 什么情况用Bert模型,什么情况用LLaMA、ChatGLM类大模型,咋选?
  • 虚幻引擎UE5入坑记
  • CANoe Trace界面介绍及Trace界面log显示不全解决方法
  • 重塑视频监控体验:WebRTC技术如何赋能智慧工厂视频高效管理场景
  • 简单工作流(后端部分-spring boot,顺便优化了下ui)
  • QT学习笔记
  • Arm 架构学习
  • Transformer中深度学习技术前提的动态展示
  • Windows系统安装MySQL
  • Swift内存管理:掌握强与弱的智能平衡术
  • [Tomcat源码解析]——源码环境搭建
  • 什么叫登录ip地址?登录ip地址可以更改吗
  • postman请求设置
  • <Rust>egui学习之小部件(三):如何为窗口UI元件设置布局(间隔、水平、垂直排列)?
  • C#入门(12)逻辑运算符
  • openEuler安装Docker和踩坑分析
  • 【经验分享】f(x)的一个原函数怎么求?
  • Python + Playwright(16):处理HTTPS错误
  • redis | 认识非关系数据库Redis的位图数据类型
  • 浅谈Sql Server 增删改查