目录
- 1. 引入依赖
- 2. 配置文件
- 3. 注解类
- 4. 切面类
- 5. 需要脱敏的实体类
- 6. 查看日志打印
1. 引入依赖
//脱敏工具包
implementation 'com.github.houbb:sensitive-core:0.0.9'
implementation 'com.alibaba:fastjson:1.2.75'
2. 配置文件
exclude.properties=name,phoneNo,password
3. 注解类
package com.example.fisher.gradledemo.annotation;
import java.lang.annotation.documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@documented
public @interface Log {
}
4. 切面类
- 提供2种方式脱敏
- fastjson脱敏字段不显示,sensitive-core将带有脱敏注解的属性字段部分显示***
package com.example.fisher.gradledemo.aspectj;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.support.spring.PropertyPreFilters;
import com.example.fisher.gradledemo.dto.LogInfo;
import com.github.houbb.sensitive.core.api.SensitiveUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
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.HashMap;
import java.util.Map;
import java.util.Set;
@Slf4j
@Component
@Aspect
public class LogAspect {
@Value("${exclude.properties}")
private Set properties;
public static final String DESENSITISE_MSG = "******";
public PropertyPreFilters.MySimplePropertyPreFilter excludePropertyPreFilter() {
return new PropertyPreFilters().addFilter().addExcludes(properties.toArray(String[]::new));
}
@Pointcut("execution(public * com.example.fisher.gradledemo.sysuser.controller.*.*(..))")
public void pc1() {}
@Pointcut("@annotation(com.example.fisher.gradledemo.annotation.Log)")
public void pc2() {}
@Around("pc1()||pc2()")
public Object around(ProceedingJoinPoint point) throws Throwable {
// 入参使用fastjson进行脱敏,脱敏字段不显示
LogInfo loginfo = getLoginfo(point);
Object result = point.proceed();
// 返回值使用sensitive-core工具包进行脱敏,脱敏字段部分显示***
Object deSensitiveObject = getDeSensitiveObject2(null, result);
loginfo.setResult(String.valueOf(deSensitiveObject));
log.info("{}", loginfo);
return result;
}
@AfterThrowing(value = "pc1()||pc2()", throwing = "e")
public void afterThrowing(JoinPoint point, Throwable e) {
LogInfo loginfo = getLoginfo(point);
log.error("{},{}", loginfo, e);
}
private LogInfo getLoginfo(JoinPoint point) {
String className = point.getTarget().getClass().getName();
MethodSignature signature = (MethodSignature)point.getSignature();
String methodName = signature.getName();
HttpServletRequest request = getRequestAttributes().getRequest();
LogInfo logInfo = new LogInfo();
logInfo.setClassName(className);
logInfo.setMethodName(methodName);
logInfo.setUrl(request.getRequestURI());
logInfo.setHttpMethod(request.getMethod());
logInfo.setIpAddress(request.getRemoteAddr());
// 获取入参
Object[] args = point.getArgs();
String[] parameterNames = signature.getParameterNames();
Map inputParam = getInputParam(parameterNames, args);
logInfo.setParameter(String.valueOf(inputParam));
return logInfo;
}
private Map getInputParam(String[] parameterNames, Object[] args) {
Map map = new HashMap<>(16);
for (int i = 0; i < parameterNames.length; i++) {
String parameterName = parameterNames[i];
Object arg = args[i];
Object deSensitiveObject = getDeSensitiveObject(parameterName, arg);
map.put(parameterName, deSensitiveObject);
}
return map;
}
private Object getDeSensitiveObject(String parameterName, Object arg) {
Class> clazz = arg.getClass();
if (arg instanceof MultipartFile || arg instanceof HttpServletRequest || arg instanceof HttpServletResponse) {
return "";
} else if (String.class.isAssignableFrom(clazz)) {
if (properties.contains(parameterName)) {
return DESENSITISE_MSG;
}
} else if (Collection.class.isAssignableFrom(clazz) || Map.class.isAssignableFrom(clazz)) {
arg = JSONObject.toJSONString(arg, excludePropertyPreFilter());
} else {
arg = JSONObject.toJSONString(arg, excludePropertyPreFilter());
}
return arg;
}
private Object getDeSensitiveObject2(String parameterName, Object arg) {
Class> clazz = arg.getClass();
if (arg instanceof MultipartFile || arg instanceof HttpServletRequest || arg instanceof HttpServletResponse) {
return "";
} else if (String.class.isAssignableFrom(clazz)) {
if (properties.contains(parameterName)) {
return DESENSITISE_MSG;
}
} else if (Collection.class.isAssignableFrom(clazz) ) {
arg = SensitiveUtil.desCopyCollection((Collection>)arg);
}else if (Map.class.isAssignableFrom(clazz)){
HashMap
5. 需要脱敏的实体类
- 在需要脱敏的属性上添加注解,例如@SensitiveStrategyChineseName,@SensitiveStrategyPhone等
- 这里使用了mybatis-plus
package com.example.fisher.gradledemo.sysuser.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.github.houbb.sensitive.annotation.strategy.SensitiveStrategyChineseName;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
@SuppressWarnings("serial")
@Data
public class SysUser extends Model {
@TableId(type = IdType.AUTO)
private Long userId;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.UPDATE)
private LocalDateTime updateTime;
@TableLogic
@JsonIgnore
private Integer delFlag;
@SensitiveStrategyChineseName
private String name;
private Integer age;
private String interest;
@Override
public Serializable pkVal() {
return this.userId;
}
}
6. 查看日志打印