Java数据 定义规则脱敏实现
步骤说明
实现 ContextualSerializer 类 重写 createContextual 方法
一、ContextualSerializer 类
官方文档解读:
接口 ContextualSerializer<T>
类型参数:
T
- 用于上下文化的序列化器类型
公共接口ContextualSerializer<T>JsonSerializer
可以实现的附加接口以获取回调,该回调可用于创建序列化程序的上下文实例以用于处理支持类型的属性。这对于可以通过注释配置的序列化程序很有用,或者应该根据正在序列化的属性类型而具有不同的行为。
createContextual 方法解读
- createContextual可以获得字段的类型以及注解。
- createContextual方法只会在第一次序列化字段时调用(因为字段的上下文信息在运行期不会改变),所以不用担心影响性能。
二、具体实现代码
1.定义注解
/*** 对象脱敏注解**/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@JacksonAnnotationsInside
@JsonSerialize(using = SensitiveSerialize.class)
public @interface Sensitive {/*** 脱敏数据类型, 非Customer时, 将忽略 refixNoMaskLen 和 suffixNoMaskLen 和 maskStr*/SensitiveTypeEnum type() default SensitiveTypeEnum.CUSTOMER;/*** 前置不需要打码的长度*/int prefixNoMaskLen() default 0;/*** 后置不需要打码的长度*/int suffixNoMaskLen() default 0;/*** 用什么打码*/String maskStr() default "*";}
2.枚举类
/*** 敏感信息枚举类***/
public enum SensitiveTypeEnum {/*** 自定义*/CUSTOMER,/*** 用户名, 刘*华, 徐**/CHINESE_NAME,/*** 身份证号, 110110********1234*/ID_CARD,/*** 座机号, ****1234*/FIXED_PHONE,/*** 手机号, 176****1234*/MOBILE_PHONE,/*** 地址, 北京*********/ADDRESS,/*** 电子邮件, s*****o@xx.com*/EMAIL,/*** 银行卡, 622202************1234*/BANK_CARD,/*** 密码, 永远是 ******, 与长度无关*/PASSWORD,/*** 密钥, 永远是 ******, 与长度无关*/KEY}
3.脱敏工具类
/*** 脱敏工具类***/
public class DesensitizedUtils {/*** 对字符串进行脱敏操作* @param origin 原始字符串* @param prefixNoMaskLen 左侧需要保留几位明文字段* @param suffixNoMaskLen 右侧需要保留几位明文字段* @param maskStr 用于遮罩的字符串, 如'*'* @return 脱敏后结果*/public static String desValue(String origin, int prefixNoMaskLen, int suffixNoMaskLen, String maskStr) {if (origin == null) {return null;}StringBuilder sb = new StringBuilder();for (int i = 0, n = origin.length(); i < n; i++) {if (i < prefixNoMaskLen) {sb.append(origin.charAt(i));continue;}if (i > (n - suffixNoMaskLen - 1)) {sb.append(origin.charAt(i));continue;}sb.append(maskStr);}return sb.toString();}/*** 【中文姓名】只显示最后一个汉字,其他隐藏为星号,比如:**梦* @param fullName 姓名* @return 结果*/public static String chineseName(String fullName) {if (fullName == null) {return null;}return desValue(fullName, 0, 1, "*");}/*** 【身份证号】显示前六位, 四位,其他隐藏。共计18位或者15位,比如:340304*******1234* @param id 身份证号码* @return 结果*/public static String idCardNum(String id) {return desValue(id, 6, 4, "*");}/*** 【固定电话】后四位,其他隐藏,比如 ****1234* @param num 固定电话* @return 结果*/public static String fixedPhone(String num) {return desValue(num, 0, 4, "*");}/*** 【手机号码】前三位,后四位,其他隐藏,比如135****6810* @param num 手机号码* @return 结果*/public static String mobilePhone(String num) {return desValue(num, 3, 4, "*");}/*** 【地址】只显示到地区,不显示详细地址,比如:北京市海淀区***** @param address 地址* @return 结果*/public static String address(String address) {return desValue(address, 6, 0, "*");}/*** 【电子邮箱 邮箱前缀仅显示第一个字母,前缀其他隐藏,用星号代替,@及后面的地址显示,比如:d**@126.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 = desValue(email.substring(0, index), 1, 0, "*");return preEmail + email.substring(index);}/*** 【银行卡号】前六位,后四位,其他用星号隐藏每位1个星号,比如:622260**********1234* @param cardNum 银行卡号* @return 结果*/public static String bankCard(String cardNum) {return desValue(cardNum, 6, 4, "*");}/*** 【密码】密码的全部字符都用*代替,比如:******* @param password 密码* @return 结果*/public static String password(String password) {if (password == null) {return null;}return "******";}/*** 【密钥】密钥除了最后三位,全部都用*代替,比如:***xdS 脱敏后长度为6,如果明文长度不足三位,则按实际长度显示,剩余位置补** @param key 密钥* @return 结果*/public static String key(String key) {if (key == null) {return null;}int viewLength = 6;StringBuilder tmpKey = new StringBuilder(desValue(key, 0, 3, "*"));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, "*");}return tmpKey.toString();}else {return tmpKey.toString();}}}
4.实现接口
@NoArgsConstructor
@AllArgsConstructor
public class SensitiveSerialize extends JsonSerializer<String> implements ContextualSerializer {private SensitiveTypeEnum type;private Integer prefixNoMaskLen;private Integer suffixNoMaskLen;private String maskStr;@Overridepublic void serialize(final String origin, final JsonGenerator jsonGenerator,final SerializerProvider serializerProvider) throws IOException {switch (type) {case CHINESE_NAME:jsonGenerator.writeString(DesensitizedUtils.chineseName(origin));break;case ID_CARD:jsonGenerator.writeString(DesensitizedUtils.idCardNum(origin));break;case FIXED_PHONE:jsonGenerator.writeString(DesensitizedUtils.fixedPhone(origin));break;case MOBILE_PHONE:jsonGenerator.writeString(DesensitizedUtils.mobilePhone(origin));break;case ADDRESS:jsonGenerator.writeString(DesensitizedUtils.address(origin));break;case EMAIL:jsonGenerator.writeString(DesensitizedUtils.email(origin));break;case BANK_CARD:jsonGenerator.writeString(DesensitizedUtils.bankCard(origin));break;case PASSWORD:jsonGenerator.writeString(DesensitizedUtils.password(origin));break;case KEY:jsonGenerator.writeString(DesensitizedUtils.key(origin));break;case CUSTOMER:jsonGenerator.writeString(DesensitizedUtils.desValue(origin, prefixNoMaskLen, suffixNoMaskLen, maskStr));break;default:throw new IllegalArgumentException("Unknow sensitive type enum " + type);}}@Overridepublic 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(), sensitive.prefixNoMaskLen(),sensitive.suffixNoMaskLen(), sensitive.maskStr());}}return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);}return serializerProvider.findNullValueSerializer(null);}}
5.使用
public class User implements Serializable {
/*** 手机号*/@Sensitive(type = SensitiveTypeEnum.MOBILE_PHONE)@ApiModelProperty(value = "手机号")private String phone;
}
总结
以上就是可以根据自定义规则定义脱敏啦!
Java数据 定义规则脱敏实现相关推荐
- java变量定义规则说法正确_下列变量命名规范说法正确的是( )。
[判断题]9.强制类型转换运算符的功能是将一个表达式的类型转换为所指定的类型. [单选题]7.已知int a[]=new int[100],在下列给出的数组元素中,非法的是 [判断题]资产,是指企业过 ...
- Java代码的维护与更新,Java常用的规则引擎,让你变动的代码更加容易维护
Java常用的规则引擎,让你变动的代码更加容易维护 Java常用的规则引擎,让你变动的代码更加容易维护 在本文中,我们将介绍Java中一些最受欢迎的规则引擎. 规则引擎由推理引擎发展而来,是一种嵌入在 ...
- Java标识符命名规则,运算符,分支结构
Java标识符命名规则,运算符,分支结构 1 Java标识符命名规则 1.1命名规则案例 163邮箱,注册邮箱名限制6~18个字符,可使用字母,数字,下划线,需要以字母开头命名规则分析1.有长度限制2 ...
- Hive:命令行界面、数据类型、DDL数据定义(数据库及表操作/分区分桶)、DML数据操作(数据导入导出)
目录 1.Hive命令行界面 1.1.选项列表 1.2.变量和属性 1.2.1.Hive中变量和属性命名空间 1.2.2.用户自定义变量 1.2.3..hiverc文件 1.3.一次使用的命令 1.4 ...
- 认识Hive,以及Hive的数据定义与数据操作,hive的数据查询和hive函数
认识Hive 为什么要出现hive 前面知识我们讲到mapreudce计算框架,各位需要通过java编码的形式来实现设计运算过程,这对各位的编程能力提出了更高的要求,难道没有门槛更低的方式来实现运算的 ...
- java中定义类的关键字是_java中定义类的关键字是什么?
java中定义类的关键字是:"class".在Java中定义一个类,需要使用"class"关键字.一个自定义的类名和一对表示程序体的大括号. 类是 Java 中 ...
- java常量定义方法_Java常量定义方法汇总
Java常量定义方法汇总 时间:2017-06-13 来源:华清远见JAVA学院 实际工作开发中,我们经常会使用到常量.那么Java常量如何定义呢?Java常量定义的规范是什么?定义Java常 ...
- Java开源的规则引擎 Drools 电商行业实战(含完整代码)
前言 我所在项目组刚好接到一个领取优惠券需求,具体需求是用户领取的各种类型的优惠券(比如:代金券.折扣券)数量不能超过某个自定义数量,因考虑到领取限制数量是动态的,另外考虑到扩展性,满足将来业务规则的 ...
- 【【SpringBoot系列】最详细demo--自定义日志脱敏组件,简单3 步完成 Spring Boot 的日志脱敏
在我们书写代码的时候,会书写许多日志代码,但是有些敏感数据是需要进行安全脱敏处理的. 对于日志脱敏的方式有很多,常见的有①使用conversionRule标签,继承MessageConverter②书 ...
最新文章
- linux expect 输入密码,shell脚本无密码登录 expect的使用方法详解
- 【优化求解】基于matlab遗传算法结合粒子群算法求解单目标优化问题【含Matlab源码 1659期】
- python编程*三角形图形创意图片_Python图形编程探索系列-04-网上图片与标签组件的结合...
- cad快速看图2020|cad迷你画图2020 附安装教程
- (七)OpenCV | 色度图
- 前端实现调取摄像头实现人脸识别
- 解决笔记本拔掉电源线和插上电源线鸣笛问题
- Notepad Next:Linux 用户的 Notepad++ 最佳替代品
- Python爬取摩拜单车位置信息
- 【刷机】小米降级刷机 线刷 图解 MIUI降级刷机
- c++读取mnn模型
- 如何快速地向服务器传大文件,大文件如何快速传输
- day9-数据库操作与Paramiko模块
- 02 【版本控制命令】
- 学生买蓝牙耳机多少钱?平价蓝牙耳机排行榜10强!
- 使用 SAP UI5 FileUploader 控件上传本地文件试读版
- 吉他弹唱精通——逆向思维玩套路
- 【愚公系列】2021年12月 Java教学课程 14-流程控制语句之while循环
- 反卷积(Deconvolution)上采样(Upsampling)上池化(Unpooling)的区别——附翻译
- PowerDesigner15及破解补丁下载