新增数据脱敏注解及实现(fastJson)
This commit is contained in:
parent
7a535d9dd2
commit
297daaec2f
|
|
@ -157,7 +157,7 @@
|
|||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template slot-scope="scope">
|
||||
<el-tooltip class="item" effect="dark" content="点击查看json格式" placement="top-start">
|
||||
<el-tooltip class="item" effect="dark" content="点击查看json格式" placement="left-start">
|
||||
<el-button circle
|
||||
type=""
|
||||
icon="el-icon-view"
|
||||
|
|
@ -315,7 +315,6 @@ export default {
|
|||
},
|
||||
/** 详细按钮操作 */
|
||||
handleView(id) {
|
||||
this.open = true;
|
||||
|
||||
getInfo(id).then(res =>{
|
||||
this.form=res.data
|
||||
|
|
@ -323,6 +322,7 @@ export default {
|
|||
try {
|
||||
this.request = JSON.parse(this.form.request)
|
||||
this.response = JSON.parse(this.form.response)
|
||||
this.open = true;
|
||||
} catch (err) {
|
||||
this.open = false;
|
||||
this.$notify({
|
||||
|
|
|
|||
|
|
@ -74,11 +74,11 @@
|
|||
<el-col :span="4">
|
||||
<div>
|
||||
<el-card shadow="hover" :body-style="{padding:'3px'}">
|
||||
<div class="board">
|
||||
<div class="top_board">IP信息</div>
|
||||
<div class="content_board">IP:<span class="num_class">{{ ipInfo.ip }}</span></div>
|
||||
<div class="content_board">归属地:<span class="num_class">{{ ipInfo.desc }}</span></div>
|
||||
</div>
|
||||
<div class="board">
|
||||
<div class="top_board">IP信息</div>
|
||||
<div class="content_board">IP:<span class="num_class">{{ ipInfo.ip }}</span></div>
|
||||
<div class="content_board">归属地:<span class="num_class">{{ ipInfo.desc }}</span></div>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</el-col>
|
||||
|
|
@ -332,7 +332,7 @@ export default {
|
|||
beautyPictureList2: [],
|
||||
beautyPictureList3: [],
|
||||
|
||||
ipInfo:{},
|
||||
ipInfo: {},
|
||||
|
||||
|
||||
};
|
||||
|
|
@ -361,14 +361,21 @@ export default {
|
|||
this.loginCount = res.data.loginCount
|
||||
this.operLogTableData = res.data.sysOperLog
|
||||
this.englishWordTableData = res.data.englishWord
|
||||
this.internalNewsList = res.data.news.internal
|
||||
this.internationalNewsList = res.data.news.international
|
||||
this.militaryNewsList = res.data.news.military
|
||||
this.beautyPictureList1 = res.data.beautyPicture.one
|
||||
this.beautyPictureList2 = res.data.beautyPicture.two
|
||||
this.beautyPictureList3 = res.data.beautyPicture.three
|
||||
if (res.data.news) {
|
||||
this.internalNewsList = res.data.news.internal;
|
||||
this.internationalNewsList = res.data.news.international;
|
||||
this.militaryNewsList = res.data.news.military;
|
||||
}
|
||||
if (res.data.beautyPicture) {
|
||||
this.beautyPictureList1 = res.data.beautyPicture.one;
|
||||
this.beautyPictureList2 = res.data.beautyPicture.two
|
||||
this.beautyPictureList3 = res.data.beautyPicture.three
|
||||
}
|
||||
|
||||
this.ipInfo = res.data.ipInfo
|
||||
|
||||
this.$modal.closeLoading()
|
||||
}).catch(err => {
|
||||
this.$modal.closeLoading()
|
||||
})
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
package com.xjs.annotation;
|
||||
|
||||
import com.xjs.enums.SensitiveTypeEnum;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 数据脱敏注解
|
||||
* @author xiejs
|
||||
* @since 2022-06-21
|
||||
*/
|
||||
@Target({ElementType.FIELD, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
public @interface Desensitized {
|
||||
// 脱敏类型(规则)
|
||||
SensitiveTypeEnum value();
|
||||
}
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
package com.xjs.config;
|
||||
|
||||
import com.alibaba.fastjson.serializer.PropertyFilter;
|
||||
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||||
import com.alibaba.fastjson.serializer.ValueFilter;
|
||||
import com.alibaba.fastjson.support.config.FastJsonConfig;
|
||||
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.xjs.config.filter.DesensitizedValueFilter;
|
||||
import com.xjs.config.filter.IgnoreNullValueFilter;
|
||||
import com.xjs.config.filter.SnowflakeValueFilter;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
|
||||
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
|
||||
|
|
@ -27,6 +27,7 @@ import java.util.List;
|
|||
@Configuration
|
||||
@Log4j2
|
||||
public class JsonConfig {
|
||||
|
||||
@Bean
|
||||
public HttpMessageConverters fastJsonHttpMessageConverters() {
|
||||
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
|
||||
|
|
@ -50,30 +51,7 @@ public class JsonConfig {
|
|||
//解决远程调用 ---(Content-Type cannot contain wildcard type '*')报错
|
||||
fastConverter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON_UTF8));
|
||||
|
||||
|
||||
//解决mp雪花算法前端精度丢失
|
||||
ValueFilter valueFilter = new ValueFilter() {
|
||||
@Override
|
||||
public Object process(Object object, String name, Object value) {
|
||||
if ((StringUtils.endsWith(name, "Id") || StringUtils.equals(name, "id")) && value != null
|
||||
&& value.getClass() == Long.class) {
|
||||
return String.valueOf(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
//忽略某些空值
|
||||
PropertyFilter filter = (source, key, value) -> {
|
||||
if (value instanceof List && ((List) value).size() == 0) {
|
||||
if ("children".equals(key)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
fastJsonConfig.setSerializeFilters(valueFilter, filter);
|
||||
fastJsonConfig.setSerializeFilters(new DesensitizedValueFilter(), new IgnoreNullValueFilter(),new SnowflakeValueFilter());
|
||||
|
||||
fastConverter.setFastJsonConfig(fastJsonConfig);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
package com.xjs.config.filter;
|
||||
|
||||
import com.alibaba.fastjson.serializer.ValueFilter;
|
||||
import com.xjs.annotation.Desensitized;
|
||||
import com.xjs.enums.SensitiveTypeEnum;
|
||||
import com.xjs.utils.DesensitizedUtils;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* 数据脱敏过滤器
|
||||
* @author xiejs
|
||||
* @since 2022-06-21
|
||||
*/
|
||||
@Log4j2
|
||||
public class DesensitizedValueFilter implements ValueFilter {
|
||||
@Override
|
||||
public Object process(Object object, String name, Object value) {
|
||||
if (null == value || !(value instanceof String) || ((String) value).length() == 0) {
|
||||
return value;
|
||||
}
|
||||
try {
|
||||
Field field = object.getClass().getDeclaredField(name);
|
||||
Desensitized desensitization;
|
||||
if (String.class != field.getType() || (desensitization = field.getAnnotation(Desensitized.class)) == null) {
|
||||
return value;
|
||||
}
|
||||
String valueStr = (String) value;
|
||||
SensitiveTypeEnum type = desensitization.value();
|
||||
switch (type) {
|
||||
case CHINESE_NAME:
|
||||
return DesensitizedUtils.chineseName(valueStr);
|
||||
case ID_CARD:
|
||||
return DesensitizedUtils.idCardNum(valueStr, 3, 3);
|
||||
case FIXED_PHONE:
|
||||
return DesensitizedUtils.fixedPhone(valueStr);
|
||||
case MOBILE_PHONE:
|
||||
return DesensitizedUtils.mobilePhone(valueStr);
|
||||
case ADDRESS:
|
||||
return DesensitizedUtils.address(valueStr, 8);
|
||||
case EMAIL:
|
||||
return DesensitizedUtils.email(valueStr);
|
||||
case BANK_CARD:
|
||||
return DesensitizedUtils.bankCard(valueStr);
|
||||
case PASSWORD:
|
||||
return DesensitizedUtils.password(valueStr);
|
||||
case CARNUMBER:
|
||||
return DesensitizedUtils.carNumber(valueStr);
|
||||
default:
|
||||
}
|
||||
} catch (NoSuchFieldException e) {
|
||||
log.error("当前数据类型为{},值为{}", object.getClass(), value);
|
||||
return value;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package com.xjs.config.filter;
|
||||
|
||||
import com.alibaba.fastjson.serializer.PropertyFilter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 忽略某些空值
|
||||
* @author xiejs
|
||||
* @since 2022-06-21
|
||||
*/
|
||||
public class IgnoreNullValueFilter implements PropertyFilter {
|
||||
|
||||
@Override
|
||||
public boolean apply(Object object, String name, Object value) {
|
||||
if (value instanceof List && ((List) value).size() == 0) {
|
||||
if ("children".equals(name)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package com.xjs.config.filter;
|
||||
|
||||
import com.alibaba.fastjson.serializer.ValueFilter;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
|
||||
/**
|
||||
* 解决mp雪花算法前端精度丢失
|
||||
* @author xiejs
|
||||
* @since 2022-06-21
|
||||
*/
|
||||
public class SnowflakeValueFilter implements ValueFilter {
|
||||
|
||||
@Override
|
||||
public Object process(Object object, String name, Object value) {
|
||||
if ((StringUtils.endsWith(name, "Id") || StringUtils.equals(name, "id")) && value != null && value.getClass() == Long.class) {
|
||||
return String.valueOf(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
package com.xjs.enums;
|
||||
|
||||
/**
|
||||
* 脱敏的实体类字段 枚举类
|
||||
* @author xiejs
|
||||
* @since 2022-06-21
|
||||
*/
|
||||
public enum SensitiveTypeEnum {
|
||||
/**
|
||||
* 中文名
|
||||
*/
|
||||
CHINESE_NAME,
|
||||
/**
|
||||
* 身份证号
|
||||
*/
|
||||
ID_CARD,
|
||||
/**
|
||||
* 座机号
|
||||
*/
|
||||
FIXED_PHONE,
|
||||
/**
|
||||
* 手机号
|
||||
*/
|
||||
MOBILE_PHONE,
|
||||
/**
|
||||
* 地址
|
||||
*/
|
||||
ADDRESS,
|
||||
/**
|
||||
* 电子邮件
|
||||
*/
|
||||
EMAIL,
|
||||
/**
|
||||
* 银行卡
|
||||
*/
|
||||
BANK_CARD,
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
PASSWORD,
|
||||
/**
|
||||
* 车牌号
|
||||
*/
|
||||
CARNUMBER;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
package com.xjs.utils;
|
||||
|
||||
import com.ruoyi.common.core.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* 脱敏工具类
|
||||
* @author xiejs
|
||||
* @since 2022-06-21
|
||||
*/
|
||||
public class DesensitizedUtils {
|
||||
/**
|
||||
* 【中文姓名】只显示第一个汉字,其他隐藏为2个星号,比如:李**
|
||||
*
|
||||
* @param fullName
|
||||
* @return
|
||||
*/
|
||||
public static String chineseName(String fullName) {
|
||||
if (StringUtils.isBlank(fullName)) {
|
||||
return "";
|
||||
}
|
||||
String name = StringUtils.left(fullName, 1);
|
||||
return StringUtils.rightPad(name, StringUtils.length(fullName), "*");
|
||||
}
|
||||
|
||||
/**
|
||||
* 【身份证号】前三位 和后三位
|
||||
*
|
||||
* @param front
|
||||
* @param end
|
||||
* @return
|
||||
*/
|
||||
public static String idCardNum(String idCardNum, int front, int end) {
|
||||
//身份证不能为空
|
||||
if (StringUtils.isEmpty(idCardNum)) {
|
||||
return "";
|
||||
}
|
||||
//需要截取的长度不能大于身份证号长度
|
||||
if ((front + end) > idCardNum.length()) {
|
||||
return "";
|
||||
}
|
||||
//需要截取的不能小于0
|
||||
if (front < 0 || end < 0) {
|
||||
return "";
|
||||
}
|
||||
//计算*的数量
|
||||
int asteriskCount = idCardNum.length() - (front + end);
|
||||
StringBuffer asteriskStr = new StringBuffer();
|
||||
for (int i = 0; i < asteriskCount; i++) {
|
||||
asteriskStr.append("*");
|
||||
}
|
||||
String regex = "(\\w{" + String.valueOf(front) + "})(\\w+)(\\w{" + String.valueOf(end) + "})";
|
||||
return idCardNum.replaceAll(regex, "$1" + asteriskStr + "$3");
|
||||
}
|
||||
|
||||
/**
|
||||
* 【固定电话 前四位,后两位
|
||||
*
|
||||
* @param num
|
||||
* @return
|
||||
*/
|
||||
public static String fixedPhone(String num) {
|
||||
if (StringUtils.isBlank(num)) {
|
||||
return "";
|
||||
}
|
||||
return StringUtils.left(num, 4).concat(StringUtils.removeStart(StringUtils.leftPad(StringUtils.right(num, 2), StringUtils.length(num), "*"), "****"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 【手机号码】前三位,后两位,其他隐藏,比如135******10
|
||||
*
|
||||
* @param num
|
||||
* @return
|
||||
*/
|
||||
public static String mobilePhone(String num) {
|
||||
if (StringUtils.isBlank(num)) {
|
||||
return "";
|
||||
}
|
||||
return StringUtils.left(num, 3).concat(StringUtils.removeStart(StringUtils.leftPad(StringUtils.right(num, 2), StringUtils.length(num), "*"), "***"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 【地址】只显示到地区,不显示详细地址,比如:北京市海淀区****
|
||||
*
|
||||
* @param address
|
||||
* @param sensitiveSize 敏感信息长度
|
||||
* @return
|
||||
*/
|
||||
public static String address(String address, int sensitiveSize) {
|
||||
if (StringUtils.isBlank(address)) {
|
||||
return "";
|
||||
}
|
||||
int length = StringUtils.length(address);
|
||||
return StringUtils.rightPad(StringUtils.left(address, length - sensitiveSize), length, "*");
|
||||
}
|
||||
|
||||
/**
|
||||
* 【电子邮箱 邮箱前缀仅显示第一个字母,前缀其他隐藏,用星号代替,@及后面的地址显示,比如:d**@126.com>
|
||||
*
|
||||
* @param email
|
||||
* @return
|
||||
*/
|
||||
public static String email(String email) {
|
||||
if (StringUtils.isBlank(email)) {
|
||||
return "";
|
||||
}
|
||||
int index = StringUtils.indexOf(email, "@");
|
||||
if (index <= 1) {
|
||||
return email;
|
||||
} else {
|
||||
return StringUtils.rightPad(StringUtils.left(email, 1), index, "*").concat(StringUtils.mid(email, index, StringUtils.length(email)));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 【银行卡号】前六位,后四位,其他用星号隐藏每位1个星号,比如:6222600**********1234>
|
||||
*
|
||||
* @param cardNum
|
||||
* @return
|
||||
*/
|
||||
public static String bankCard(String cardNum) {
|
||||
if (StringUtils.isBlank(cardNum)) {
|
||||
return "";
|
||||
}
|
||||
return StringUtils.left(cardNum, 6).concat(StringUtils.removeStart(StringUtils.leftPad(StringUtils.right(cardNum, 4), StringUtils.length(cardNum), "*"), "******"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 【密码】密码的全部字符都用*代替,比如:******
|
||||
*
|
||||
* @param password
|
||||
* @return
|
||||
*/
|
||||
public static String password(String password) {
|
||||
if (StringUtils.isBlank(password)) {
|
||||
return "";
|
||||
}
|
||||
String pwd = StringUtils.left(password, 0);
|
||||
return StringUtils.rightPad(pwd, StringUtils.length(password), "*");
|
||||
}
|
||||
|
||||
/**
|
||||
* 【车牌号】前两位后一位,比如:苏M****5
|
||||
*
|
||||
* @param carNumber
|
||||
* @return
|
||||
*/
|
||||
public static String carNumber(String carNumber) {
|
||||
if (StringUtils.isBlank(carNumber)) {
|
||||
return "";
|
||||
}
|
||||
return StringUtils.left(carNumber, 2).
|
||||
concat(StringUtils.removeStart(StringUtils.leftPad(StringUtils.right(carNumber, 1), StringUtils.length(carNumber), "*"), "**"));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -3,6 +3,8 @@ package com.xjs.maillog.domain;
|
|||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.ruoyi.common.core.annotation.Excel;
|
||||
import com.xjs.annotation.Desensitized;
|
||||
import com.xjs.enums.SensitiveTypeEnum;
|
||||
import com.xjs.validation.group.SelectGroup;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
|
@ -42,6 +44,7 @@ public class MailLog implements Serializable {
|
|||
*/
|
||||
@Excel(name = "收件人")
|
||||
@Size(max = 20, message = "请控制收件人长度在20字符", groups = { SelectGroup.class})
|
||||
@Desensitized(SensitiveTypeEnum.EMAIL)
|
||||
private String recipient;
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in New Issue