1. 自定义脱敏注解
package com.hanhuide.hhde.annotation; import com.hanhuide.hhde.enums.SensitiveTypeEnum; import java.lang.annotation.*; @Target({ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface Desensitized { // 脱敏类型(规则) SensitiveTypeEnum type(); }
2.定义脱敏类型
package com.hanhuide.hhde.enums; public enum SensitiveTypeEnum { /** * 中文名 */ CHINESE_NAME, /** * 身份证号 */ ID_CARD, /** * 座机号 */ FIXED_PHONE, /** * 手机号 */ MOBILE_PHONE, /** * 地址 */ ADDRESS, /** * 电子邮件 */ EMAIL, /** * 银行卡 */ BANK_CARD, /** * 密码 */ PASSWORD, /** * 车牌号 */ CARNUMBER; }
3. 编辑脱敏工具类
package com.hanhuide.hhde.utils; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.serializer.SerializerFeature; import com.hanhuide.hhde.annotation.Desensitized; import org.apache.commons.lang3.StringUtils; import java.lang.reflect.*; import java.util.*; /** * @Title: DesensitizedUtils */ 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), "*"); } /** * 【身份证号】显示最后四位,其他隐藏。共计18位或者15位,比如:*************1234 * * @param id * @return */ public static String idCardNum(String id) { if (StringUtils.isBlank(id)) { return ""; } String num = StringUtils.right(id, 4); return StringUtils.leftPad(num, StringUtils.length(id), "*"); } /** * 【固定电话 后四位,其他隐藏,比如1234 * * @param num * @return */ public static String fixedPhone(String num) { if (StringUtils.isBlank(num)) { return ""; } return StringUtils.leftPad(StringUtils.right(num, 4), 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), "*"), "**")); } }
4. 实现ValueFilter 接口 在process添加自己的处理步骤
package com.hanhuide.hhde.filter; import com.alibaba.fastjson.serializer.ValueFilter; import java.lang.reflect.Field; import com.hanhuide.hhde.annotation.Desensitized; import com.hanhuide.hhde.enums.SensitiveTypeEnum; import com.hanhuide.hhde.utils.DesensitizedUtils; import lombok.extern.slf4j.Slf4j; /** * 在fastjson中使用此过滤器进行脱敏操作 */ @Slf4j public class ValueDesensitizeFilter 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.type(); switch (type) { case CHINESE_NAME: return DesensitizedUtils.chineseName(valueStr); case ID_CARD: return DesensitizedUtils.idCardNum(valueStr); 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; } }
5. 配置fastjson为默认JSON转换
package com.hanhuide.hhde.config; import com.alibaba.fastjson.serializer.SerializerFeature; import com.alibaba.fastjson.support.config.FastJsonConfig; import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; import com.hanhuide.hhde.factory.DesensitizedAnnotationFormatterFactory; import com.hanhuide.hhde.filter.ValueDesensitizeFilter; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.http.HttpMessageConverters; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.format.FormatterRegistry; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.util.ArrayList; import java.util.List; @Configuration @Slf4j public class WebConfigurer implements WebMvcConfigurer { @Override public void addFormatters(FormatterRegistry registry) { log.info("启用自定义注解!!!"); registry.addFormatterForFieldAnnotation(new DesensitizedAnnotationFormatterFactory()); } /** * 配置fastjson为默认JSON转换 * * @return */ @Bean public HttpMessageConverters fastJsonHttpMessageConverters() { // 1.定义一个converters转换消息的对象 FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter(); // 2.添加fastjson的配置信息,比如: 是否需要格式化返回的json数据 FastJsonConfig fastJsonConfig = new FastJsonConfig(); fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat); fastJsonConfig.setSerializeFilters(new ValueDesensitizeFilter());//添加自己写的拦截器 // 3.在converter中添加配置信息 fastConverter.setFastJsonConfig(fastJsonConfig); // 4.将converter赋值给HttpMessageConverter HttpMessageConverter<?> converter = fastConverter; // 5.返回HttpMessageConverters对象 return new HttpMessageConverters(converter);