原有切面形式对controller进来的请求记录日志,但对于一些敏感信息,比如密码、手机号打印在日志中存在泄露风险
由于应用中已经使用了AOP的方式记录请求日志,所以直接从切面判断并且将内容转密文打印。为了更加方便、灵活的设置需要遮掩的字段内容,采用注解的方式将需要遮掩的字段标记,在切面中进行识别处理
需要处理字段标记注解
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface EncryptLog {
}
应用拦截请求日志代码
@Aspect
@Component
@Slf4j
public class WebLogAspect {
/**
* 指定 controller 包下的注解
*/
@Pointcut("execution( * com.test.cloud.api.web.controller.*.*(..))")
public void logPointCut() {
}
/**
* 指定当前执行方法在logPointCut之前执行
*/
@Before("logPointCut()")
public void doBefore(JoinPoint joinPoint) {
MDC.put("TRACE_ID", StrUtil.removeAll(UUID.randomUUID().toString(), "-"));
// 接收到请求,记录请求内容
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
List<Object> printArgs = getPrintArgs(joinPoint.getArgs());
// 记录下请求内容
log.info("请求ip:{},请求地址:{},请求类型:{}", HttpUtils.getIpAddr(request), request.getRequestURL().toString(), request.getMethod());
log.info("请求方法:{}", joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
log.info("参数:{}", printArgs.toArray());
}
@NotNull
private List<Object> getPrintArgs(Object[] args) {
List<Object> printArgs = new ArrayList<>(args.length);
for (Object arg : args) {
if (arg instanceof ServletRequest || arg instanceof ServletResponse) {
continue;
}
//复制一份,避免修改原内容
Object copyArg = BeanUtil.copyProperties(arg, arg.getClass());
for (Field field : copyArg.getClass().getDeclaredFields()) {
EncryptLog tag = field.getAnnotation(EncryptLog.class);
if (tag != null) {
field.setAccessible(true);
try {
field.set(copyArg, "******");
} catch (IllegalAccessException e) {
log.error(e.getMessage(), e);
}
}
}
printArgs.add(copyArg);
}
return printArgs;
}
/**
* 指定在方法之后返回
*/
@AfterReturning(returning = "ret", pointcut = "logPointCut()")
public void doAfterReturning(Object ret) {
// 处理完请求,返回内容
log.info("返回值 :{}", getPrintArgs(new Object[]{ret}));
MDC.clear();
}
@Around("logPointCut()")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
StopWatch sw = new StopWatch();
sw.start();
Object ob = pjp.proceed();
sw.stop();
log.info("耗时 :{} ms", sw.getTotalTimeMillis());
return ob;
}
demo
@Data
public class AccountLoginRequest {
@NotBlank(message = "请填写账号")
private String account;
@EncryptLog
@NotBlank(message = "请填写密码")
private String password;
}
效果
请求ip:127.0.0.1,请求地址:http://127.0.0.1:8999/login/account,请求类型:POST
请求方法:com.test.cloud.api.web.controller.UserLoginController.accountLogin
参数:AccountLoginRequest(account=test@163.com, password=******)
本文来自博客园,作者:IAyue,转载请注明原文链接:https://www.cnblogs.com/zmj-pr/p/17664331.html
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://www.cnblogs.com/zmj-pr/p/17664331.html
内容来源于网络,如有侵权,请联系作者删除!