注解进行数据脱敏处理()-其他
注解进行数据脱敏处理()
1.定义注解和枚举类
package com.joolun.common.sensitive;
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 脱敏注解
*
* @author JooLun
* @Author: https://www.cnblogs.com/xiluonanfeng/p/10183926.html
**/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@JacksonAnnotationsInside
@JsonSerialize(using = SensitiveSerialize.class)
public @interface Sensitive {
/**
* 脱敏数据类型
*/
SensitiveTypeEnum type();
}
package com.joolun.common.sensitive;
/**
* 敏感信息枚举类
*
* @author JooLun
* @Author: https://www.cnblogs.com/xiluonanfeng/p/10183926.html
**/
public enum SensitiveTypeEnum {
/**
* 用户名, 李*天, 张*
*/
CHINESE_NAME,
/**
* 手机号, 185****1653
*/
MOBILE_PHONE,
/**
* 电子邮件, r*****o@qq.com
*/
EMAIL,
/**
* 密码, ******
*/
PASSWORD,
/**
* 密钥, 最后三位其他都是***
*/
KEY
}
2.脱敏工具类和业务类
package com.joolun.common.sensitive;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.joolun.common.utils.SensitiveUtils;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import java.io.IOException;
import java.util.Objects;
/**
* @author JooLun
* @Author: https://www.cnblogs.com/xiluonanfeng/p/10183926.html
* 脱敏序列化
*/
@NoArgsConstructor
@AllArgsConstructor
public class SensitiveSerialize extends JsonSerializer<String> implements ContextualSerializer {
private SensitiveTypeEnum type;
@Override
public void serialize(final String originStr, final JsonGenerator jsonGenerator,
final SerializerProvider serializerProvider) throws IOException {
switch (type) {
case CHINESE_NAME:
jsonGenerator.writeString(SensitiveUtils.chineseName(originStr));
break;
case MOBILE_PHONE:
jsonGenerator.writeString(SensitiveUtils.mobilePhone(originStr));
break;
case EMAIL:
jsonGenerator.writeString(SensitiveUtils.email(originStr));
break;
case PASSWORD:
jsonGenerator.writeString(SensitiveUtils.password(originStr));
break;
case KEY:
jsonGenerator.writeString(SensitiveUtils.key(originStr));
break;
default:
throw new IllegalArgumentException("未定义的敏感信息枚举类" + type);
}
}
@Override
public JsonSerializer<?> createContextual(final SerializerProvider serializerProvider, final BeanProperty beanProperty) throws JsonMappingException {
if (beanProperty != null) {
if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) {
Sensitive sensitive = beanProperty.getAnnotation(Sensitive.class);
if (sensitive == null) {
sensitive = beanProperty.getContextAnnotation(Sensitive.class);
}
if (sensitive != null) {
return new SensitiveSerialize(sensitive.type());
}
}
return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
}
return serializerProvider.findNullValueSerializer(null);
}
}
package com.joolun.common.utils;
import cn.hutool.core.util.StrUtil;
/**
* 数据脱敏工具类
*
* @Author: JooLun
* @Author: https://www.cnblogs.com/xiluonanfeng/p/10183926.html
* @Date: 2021/7/19 16:21
*/
public class SensitiveUtils {
/**
* 默认填充字符
*/
public static final String DEFAULT_PAD_STR = "*";
/**
* 数据脱敏
*
*/
public static String process(String data) {
return process(data, 2, 1, DEFAULT_PAD_STR);
}
/**
* 数据脱敏
*
*/
public static String process(String data, Integer leftLen, Integer rightLen) {
return process(data, leftLen, rightLen, DEFAULT_PAD_STR);
}
/**
* 对字符串进行脱敏操作
* @param originStr 原始字符串
* @param prefixNoMaskLen 左侧需要保留几位明文字段
* @param suffixNoMaskLen 右侧需要保留几位明文字段
* @param maskStr 用于遮罩的字符串, 如'*'
* @return 脱敏后结果
*/
public static String process(String originStr, int prefixNoMaskLen, int suffixNoMaskLen, String maskStr) {
if (originStr == null) {
return null;
}
StringBuilder sb = new StringBuilder();
for (int i = 0, n = originStr.length(); i < n; i++) {
if (i < prefixNoMaskLen) {
sb.append(originStr.charAt(i));
continue;
}
if (i > (n - suffixNoMaskLen - 1)) {
sb.append(originStr.charAt(i));
continue;
}
sb.append(maskStr);
}
return sb.toString();
}
/**
* 中文姓名只显示最后一个汉字
* @param fullName 姓名
* @return
*/
public static String chineseName(String fullName) {
if (fullName == null) {
return null;
}
return process(fullName, 0, 1, DEFAULT_PAD_STR);
}
/**
* 手机号码前三位,后四位,如186****2356
* @param num 手机号码
* @return
*/
public static String mobilePhone(String num) {
return process(num, 0, 4, DEFAULT_PAD_STR);
}
/**
* 地址只显示到地区
* @param address 地址
* @return
*/
public static String address(String address) {
return process(address, 6, 0, DEFAULT_PAD_STR);
}
/**
* 电子邮箱 仅显示第一个字母,@后面的地址显示,比如:r**@qq.com
* @param email 电子邮箱
* @return
*/
public static String email(String email) {
if (email == null) {
return null;
}
int index = StrUtil.indexOf(email, '@');
if (index <= 1) {
return email;
}
String preEmail = process(email.substring(0, index), 1, 0, DEFAULT_PAD_STR);
return preEmail + email.substring(index);
}
/**
* 密码的全部字符,如:******
* @param password 密码
* @return
*/
public static String password(String password) {
if (password == null) {
return null;
}
return "******";
}
/**
* 密钥除了最后三位,全部,比如:***klo
* @param key 密钥
* @return 结果
*/
public static String key(String key) {
if (key == null) {
return null;
}
int viewLength = 6;
StringBuilder tmpKey = new StringBuilder(process(key, 0, 3, DEFAULT_PAD_STR));
if (tmpKey.length() > viewLength) {
return tmpKey.substring(tmpKey.length() - viewLength);
}
else if (tmpKey.length() < viewLength) {
int buffLength = viewLength - tmpKey.length();
for (int i = 0; i < buffLength; i++) {
tmpKey.insert(0, DEFAULT_PAD_STR);
}
return tmpKey.toString();
}
else {
return tmpKey.toString();
}
}
public static void main(String[] args) {
String s = mobilePhone("18653653621");
System.out.println(s);
}
}
3.实体类使用
/**
* 电话号码
*/
@ApiModelProperty(value = "电话号码")
@Sensitive(type = SensitiveTypeEnum.MOBILE_PHONE)
private String telNum;
————————
1.定义注解和枚举类
package com.joolun.common.sensitive;
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 脱敏注解
*
* @author JooLun
* @Author: https://www.cnblogs.com/xiluonanfeng/p/10183926.html
**/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@JacksonAnnotationsInside
@JsonSerialize(using = SensitiveSerialize.class)
public @interface Sensitive {
/**
* 脱敏数据类型
*/
SensitiveTypeEnum type();
}
package com.joolun.common.sensitive;
/**
* 敏感信息枚举类
*
* @author JooLun
* @Author: https://www.cnblogs.com/xiluonanfeng/p/10183926.html
**/
public enum SensitiveTypeEnum {
/**
* 用户名, 李*天, 张*
*/
CHINESE_NAME,
/**
* 手机号, 185****1653
*/
MOBILE_PHONE,
/**
* 电子邮件, r*****o@qq.com
*/
EMAIL,
/**
* 密码, ******
*/
PASSWORD,
/**
* 密钥, 最后三位其他都是***
*/
KEY
}
2.脱敏工具类和业务类
package com.joolun.common.sensitive;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.joolun.common.utils.SensitiveUtils;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import java.io.IOException;
import java.util.Objects;
/**
* @author JooLun
* @Author: https://www.cnblogs.com/xiluonanfeng/p/10183926.html
* 脱敏序列化
*/
@NoArgsConstructor
@AllArgsConstructor
public class SensitiveSerialize extends JsonSerializer<String> implements ContextualSerializer {
private SensitiveTypeEnum type;
@Override
public void serialize(final String originStr, final JsonGenerator jsonGenerator,
final SerializerProvider serializerProvider) throws IOException {
switch (type) {
case CHINESE_NAME:
jsonGenerator.writeString(SensitiveUtils.chineseName(originStr));
break;
case MOBILE_PHONE:
jsonGenerator.writeString(SensitiveUtils.mobilePhone(originStr));
break;
case EMAIL:
jsonGenerator.writeString(SensitiveUtils.email(originStr));
break;
case PASSWORD:
jsonGenerator.writeString(SensitiveUtils.password(originStr));
break;
case KEY:
jsonGenerator.writeString(SensitiveUtils.key(originStr));
break;
default:
throw new IllegalArgumentException("未定义的敏感信息枚举类" + type);
}
}
@Override
public JsonSerializer<?> createContextual(final SerializerProvider serializerProvider, final BeanProperty beanProperty) throws JsonMappingException {
if (beanProperty != null) {
if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) {
Sensitive sensitive = beanProperty.getAnnotation(Sensitive.class);
if (sensitive == null) {
sensitive = beanProperty.getContextAnnotation(Sensitive.class);
}
if (sensitive != null) {
return new SensitiveSerialize(sensitive.type());
}
}
return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
}
return serializerProvider.findNullValueSerializer(null);
}
}
package com.joolun.common.utils;
import cn.hutool.core.util.StrUtil;
/**
* 数据脱敏工具类
*
* @Author: JooLun
* @Author: https://www.cnblogs.com/xiluonanfeng/p/10183926.html
* @Date: 2021/7/19 16:21
*/
public class SensitiveUtils {
/**
* 默认填充字符
*/
public static final String DEFAULT_PAD_STR = "*";
/**
* 数据脱敏
*
*/
public static String process(String data) {
return process(data, 2, 1, DEFAULT_PAD_STR);
}
/**
* 数据脱敏
*
*/
public static String process(String data, Integer leftLen, Integer rightLen) {
return process(data, leftLen, rightLen, DEFAULT_PAD_STR);
}
/**
* 对字符串进行脱敏操作
* @param originStr 原始字符串
* @param prefixNoMaskLen 左侧需要保留几位明文字段
* @param suffixNoMaskLen 右侧需要保留几位明文字段
* @param maskStr 用于遮罩的字符串, 如'*'
* @return 脱敏后结果
*/
public static String process(String originStr, int prefixNoMaskLen, int suffixNoMaskLen, String maskStr) {
if (originStr == null) {
return null;
}
StringBuilder sb = new StringBuilder();
for (int i = 0, n = originStr.length(); i < n; i++) {
if (i < prefixNoMaskLen) {
sb.append(originStr.charAt(i));
continue;
}
if (i > (n - suffixNoMaskLen - 1)) {
sb.append(originStr.charAt(i));
continue;
}
sb.append(maskStr);
}
return sb.toString();
}
/**
* 中文姓名只显示最后一个汉字
* @param fullName 姓名
* @return
*/
public static String chineseName(String fullName) {
if (fullName == null) {
return null;
}
return process(fullName, 0, 1, DEFAULT_PAD_STR);
}
/**
* 手机号码前三位,后四位,如186****2356
* @param num 手机号码
* @return
*/
public static String mobilePhone(String num) {
return process(num, 0, 4, DEFAULT_PAD_STR);
}
/**
* 地址只显示到地区
* @param address 地址
* @return
*/
public static String address(String address) {
return process(address, 6, 0, DEFAULT_PAD_STR);
}
/**
* 电子邮箱 仅显示第一个字母,@后面的地址显示,比如:r**@qq.com
* @param email 电子邮箱
* @return
*/
public static String email(String email) {
if (email == null) {
return null;
}
int index = StrUtil.indexOf(email, '@');
if (index <= 1) {
return email;
}
String preEmail = process(email.substring(0, index), 1, 0, DEFAULT_PAD_STR);
return preEmail + email.substring(index);
}
/**
* 密码的全部字符,如:******
* @param password 密码
* @return
*/
public static String password(String password) {
if (password == null) {
return null;
}
return "******";
}
/**
* 密钥除了最后三位,全部,比如:***klo
* @param key 密钥
* @return 结果
*/
public static String key(String key) {
if (key == null) {
return null;
}
int viewLength = 6;
StringBuilder tmpKey = new StringBuilder(process(key, 0, 3, DEFAULT_PAD_STR));
if (tmpKey.length() > viewLength) {
return tmpKey.substring(tmpKey.length() - viewLength);
}
else if (tmpKey.length() < viewLength) {
int buffLength = viewLength - tmpKey.length();
for (int i = 0; i < buffLength; i++) {
tmpKey.insert(0, DEFAULT_PAD_STR);
}
return tmpKey.toString();
}
else {
return tmpKey.toString();
}
}
public static void main(String[] args) {
String s = mobilePhone("18653653621");
System.out.println(s);
}
}
3.实体类使用
/**
* 电话号码
*/
@ApiModelProperty(value = "电话号码")
@Sensitive(type = SensitiveTypeEnum.MOBILE_PHONE)
private String telNum;