package org.springblade.common.desensitization;
|
|
import cn.hutool.core.convert.Convert;
|
import cn.hutool.core.util.DesensitizedUtil;
|
import cn.hutool.core.util.StrUtil;
|
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONPath;
|
import liquibase.util.StringUtils;
|
import lombok.extern.slf4j.Slf4j;
|
import org.aspectj.lang.ProceedingJoinPoint;
|
import org.aspectj.lang.annotation.Around;
|
import org.aspectj.lang.annotation.Aspect;
|
import org.springblade.core.secure.utils.AuthUtil;
|
import org.springframework.stereotype.Component;
|
|
import static cn.hutool.core.util.DesensitizedUtil.DesensitizedType.FIXED_PHONE;
|
|
/**
|
* 数据脱敏切面
|
* @author zhongrj
|
* @date 2023-09-11
|
*/
|
@Slf4j
|
@Aspect
|
@Component
|
public class DesensitizationAspect {
|
|
/**
|
* 脱敏环绕通知
|
* @param pjp
|
* @param desensitizationWord
|
* @return
|
* @throws Throwable
|
*/
|
@Around("@annotation(desensitizationWord)")
|
public Object around(ProceedingJoinPoint pjp, DesensitizationWord desensitizationWord) throws Throwable{
|
Object object = pjp.proceed();
|
// 判断是否需要脱敏处理
|
if (isDesensitization()) {
|
try {
|
Class<?> aClass = object.getClass();
|
// 改变返回值
|
Desensitization[] value = desensitizationWord.value();
|
JSONObject ob = JSON.parseObject(JSON.toJSONString(object));
|
|
// 循环处理每一个 json 路径下的值
|
for (Desensitization s : value) {
|
replace(ob, s);
|
}
|
object = JSON.parseObject(JSON.toJSONString(ob), aClass);
|
} catch (Exception e) {
|
log.info("数据脱敏失败:" + e.getMessage());
|
}
|
}
|
return object;
|
}
|
|
/**
|
* 判断是否需要脱敏
|
* @return
|
*/
|
private boolean isDesensitization() {
|
// 获取用户角色,根据角色判断是否进行脱敏处理
|
String userRole = AuthUtil.getUserRole();
|
// 如果用户角色为null,则需要脱敏
|
if (null!=userRole && !userRole.equals("")){
|
// 判断角色是否为民警角色,如果是则不需要脱敏,否则需要脱敏处理
|
if (userRole.equals("民警")){
|
return false;
|
}
|
}
|
return true;
|
}
|
|
/**
|
* 脱敏
|
*/
|
private Object sensitiveByString(Object value) {
|
if (StringUtils.isNotEmpty(value.toString())) {
|
String st = Convert.toStr(value);
|
st = st.substring(0, st.length() - 3 > 0 ? 3 : st.length()) + "****" + st.substring(Math.max(st.length() - 4, 0));
|
return st;
|
}
|
return value;
|
}
|
|
/**
|
* 敏感数据替换
|
*
|
* @param jsonObject
|
* @param s
|
*/
|
private void replace(JSONObject jsonObject, Desensitization s) {
|
// 只有传入的 JSON 路径在 这个 JSONObject 中才会进行脱敏处理
|
if (JSONPath.contains(jsonObject, s.jsonPath())) {
|
|
// 查询是否有数组 列表 类型的数据需要脱敏
|
int index = s.jsonPath().lastIndexOf("[*]");
|
if (index > -1) {
|
String prefix = StrUtil.subPre(s.jsonPath(), index);
|
String suffix = StrUtil.subSuf(s.jsonPath(), index + 3);
|
// 提取json 路径下的 数组\链表 元素
|
Object eval = JSONPath.eval(jsonObject, prefix);
|
|
// 将数组\链表 元素 转为 JSONArray 方便做 统一格式处理
|
JSONArray jsonArray = (JSONArray) eval;
|
int size = jsonArray.size();
|
for (int i = 0; i < size; i++) {
|
// 由于脱敏数组内部的参数传入格式为 :jsonPath = "$.data.records[*].username"
|
// 所以需要重新组装 jsonPath 将 * 号 替换成具体的值
|
String indexJsonPath = StrUtil.strBuilder().append(prefix).append("[").append(i).append("]").append(suffix).toString();
|
// 使用 cn.hutool.core.convert Convert.toStr 转换为字符串 如果给定的值为null,或者转换失败,返回默认值null,这样可以减少报错,避免程序异常
|
String desensitized = Convert.toStr(JSONPath.eval(jsonObject, indexJsonPath));
|
if (StrUtil.isBlank(desensitized)) {
|
continue;
|
}
|
// 如果是默认指定 则使用默认方式脱敏
|
if (s.desensitizedType() == FIXED_PHONE) {
|
desensitized = sensitiveByString(desensitized).toString();
|
}else {
|
// 否则使用 cn.hutool.core.util 进行数据脱敏
|
desensitized = DesensitizedUtil.desensitized(desensitized, s.desensitizedType());
|
}
|
|
// 使用JSON 路径操作,将已经脱敏的新数据,放入之前未脱敏的数据地址处,替换未脱敏数据
|
JSONPath.set(jsonObject, indexJsonPath, desensitized);
|
}
|
} else {
|
// 使用 cn.hutool.core.convert Convert.toStr 转换为字符串 如果给定的值为null,或者转换失败,返回默认值null,这样可以减少报错,避免程序异常
|
Object eval = JSONPath.eval(jsonObject, Convert.toStr(s.jsonPath()));
|
String desensitized = "";
|
if (s.desensitizedType() == FIXED_PHONE) {
|
desensitized = sensitiveByString(Convert.toStr(eval)).toString();
|
}else {
|
desensitized = DesensitizedUtil.desensitized(Convert.toStr(eval), s.desensitizedType());
|
}
|
JSONPath.set(jsonObject, s.jsonPath(), desensitized);
|
}
|
}
|
}
|
}
|