springboot返回数据显示成星号*号 字段脱敏

导读:本篇文章讲解 springboot返回数据显示成星号*号 字段脱敏,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/a1053765496/article/details/120483598

 springboot返回数据显示成星号*号 字段脱敏

先上效果图:

springboot返回数据显示成星号*号 字段脱敏

开始

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 lixx
 * @version 1.0
 * @since 2021-08-25 17:18
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = SensitiveSerializer.class)
public @interface Sensitive {

	/**
	 * 前缀长度,优先级L2
	 */
	int prefix() default 3;

	/**
	 * 后缀长度,优先级L2
	 */
	int suffix() default 4;

	/**
	 * 脱敏替换字符,优先级L1
	 */
	String maskChar() default "*";

	/**
	 * 脱敏数据类型,优先级L1,L2优先级配置失效
	 */
	SensitiveEnum type() default SensitiveEnum.NONE;

}
import lombok.AllArgsConstructor;
import lombok.Getter;

/**
 * 脱敏类型枚举
 *
 * @author lixx
 * @version 1.0
 * @since 2021-08-25 17:19
 */
@Getter
@AllArgsConstructor
public enum SensitiveEnum {

	/**
	 * 中文名,只显示最后一位
	 * 只有中文才生效
	 */
	CHINESE_NAME(0, 1),

	/**
	 * 中文名2,只隐藏第一位
	 * 只有中文才生效
	 */
	CHINESE_NAME2(-1, 0),

	/**
	 * 手机号码,显示开头3位,后4位,中间隐藏
	 */
	PHONE(3, 4),

	/**
	 * 银行卡,显示开头2 ,结束2,中间隐藏
	 */
	BANK_CARD(2, 2),

	/**
	 * 身份证号码,显示前面2位,和后面4位,其他隐藏
	 */
	ID_CARD(2, 4),

	/**
	 * 电子邮箱,显示开头1位结尾1位,以及@后面的
	 */
	EMAIL(1, 1),

	;

	public final int prefixLength;

	public final int suffixLength;

}
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 lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 自定义脱敏数据序列化
 *
 * @author lixx
 * @version 1.0
 * @since 2021-08-25 18:01
 */
@NoArgsConstructor
@AllArgsConstructor
public class SensitiveSerializer extends JsonSerializer<Object> implements ContextualSerializer {

	private int prefixLength;

	private int suffixLength;

	private String maskChar;

	private SensitiveEnum sensitiveEnum;

	public final static String template = "(?<=\\w{%s})\\w(?=\\w{%s})";

	@Override
	public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
		if (Objects.nonNull(value)) {
			if (value instanceof String[]) {
				String[] arr = (String[]) value;
				gen.writeStartArray();
				for (String s : arr) {
					gen.writeString(s.trim().replaceAll(String.format(template, prefixLength, suffixLength), maskChar));
				}
				gen.writeEndArray();
			}

			if (value instanceof List) {
				List<?> list = (List<?>) value;
				if (!CollectionUtils.isEmpty(list) && list.get(0).getClass().equals(String.class)) {
					gen.writeStartArray();
					for (Object o : list) {
						gen.writeString(((String) o).trim().replaceAll(String.format(template, prefixLength, suffixLength), maskChar));
					}
					gen.writeEndArray();
				}
			}
			if (value instanceof String) {
				String val = value.toString();
				if (sensitiveEnum.equals(SensitiveEnum.CHINESE_NAME) || sensitiveEnum.equals(SensitiveEnum.CHINESE_NAME2)) {
					if (checkCountName(val)) {
						if (prefixLength == -1) {
							gen.writeString(StringUtils.leftPad(StringUtils.right(val, val.length() - 1), val.length(), maskChar));
						} else {
							String left = StringUtils.left(val, prefixLength);
							gen.writeString(StringUtils.rightPad(left, val.length() - suffixLength, maskChar).concat(StringUtils.right(val, suffixLength)));
						}
					} else {
						gen.writeString(((String) value).trim().replaceAll(String.format(template, prefixLength, suffixLength), maskChar));
					}
				} else {
					if (checkEmail(val)) {
						gen.writeString(email(val, prefixLength, suffixLength, maskChar));
					} else {
						gen.writeString(((String) value).trim().replaceAll(String.format(template, prefixLength, suffixLength), maskChar));
					}
				}
			}
		}
	}

	@Override
	public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
		if (Objects.nonNull(property)) {
			Sensitive mask = property.getAnnotation(Sensitive.class);
			if (Objects.isNull(mask)) {
				mask = property.getContextAnnotation(Sensitive.class);
			}
			//可以改造成初始化regex正则表达式
			if (mask.type().equals(SensitiveEnum.NONE)) {
				return new SensitiveSerializer(mask.prefix(), mask.suffix(), mask.maskChar(), mask.type());
			} else {
				return new SensitiveSerializer(mask.type().prefixLength, mask.type().suffixLength, mask.maskChar(), mask.type());
			}
		} else {
			return prov.findNullValueSerializer(null);
		}
	}

	@Override
	public Class<Object> handledType() {
		return Object.class;
	}

	/**
	 * 判断是否是汉字
	 */
	private boolean checkCountName(String countName) {
		Pattern p = Pattern.compile("[\u4e00-\u9fa5]");
		Matcher m = p.matcher(countName);
		return m.find();
	}

	/**
	 * 判断是否是邮箱格式
	 */
	private boolean checkEmail(String email) {
		Pattern patten = Pattern.compile("[\\w]+@([\\w]+.)+[\\w]+");
		Matcher matcher = patten.matcher(email);
		return matcher.matches();
	}

	public static String email(String email, int prefixLength, int suffixLength, String maskChar) {
		if (StringUtils.isBlank(email)) {
			return "";
		}
		int index = StringUtils.indexOf(email, "@");
		if (index <= prefixLength + suffixLength) {
			return email;
		} else {
			String emailPrefix = email.substring(0, index);
			String emailSuffix = email.substring(index);
			return emailPrefix.replaceAll(String.format(template, prefixLength, suffixLength), maskChar).concat(emailSuffix);
		}
	}

}

使用如下:

/**
 * @author lixx
 * @version 1.0
 * @since 2021-07-22 19:26
 */
@Data
public class SysUser {

	/**
	 * 手机号码,需要脱敏的属性字段
	 */
	@Sensitive(type = SensitiveEnum.PHONE)
	private String mobile;

}

 效果如下:

springboot返回数据显示成星号*号 字段脱敏

springboot返回数据显示成星号*号 字段脱敏

结语:

springboot返回数据显示成星号*号 字段脱敏

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/72541.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!