什么是脱敏
数据脱敏是指对某些敏感信息通过脱敏规则进行数据的变形,实现敏感隐私数据的可靠保护。在涉及客户安全数据或者一些商业性敏感数据的情况下,在不违反系统规则条件下,对真实数据进行改造并提供测试使用,如身份证号、手机号、卡号、客户号等个人信息都需要进行数据脱敏。
如何使用注解式数据脱敏
01 创建对属性脱敏处理的工具类 SensitiveInfoUtils
/**
* 数据脱敏
*/
public class SensitiveInfoUtils {
/**
* [中文姓名] 只显示第一个汉字,其他隐藏为星号<例子:李**>
* @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 familyName 姓氏
* @param givenName 名字
* @return
*/
public static String chineseName(String familyName, String givenName) {
if (StringUtils.isBlank(familyName) || StringUtils.isBlank(givenName)) {
return "";
}
if(familyName.length()>1){
String name = StringUtils.left(familyName, familyName.length());
return StringUtils.rightPad(name, StringUtils.length(familyName+givenName), "*");
}
return chineseName(familyName + givenName);
}
/**
* [身份证号] 显示最后四位,其他隐藏。共计18位或者15位。<例子:*************5762>
*
* @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), "*");
}
/**
* [身份证号] 前六位,后四位,其他用星号隐藏每位1个星号<例子:451002********1647>
*
* @param carId
* @return
*/
public static String idCard(String carId){
if (StringUtils.isBlank(carId)) {
return "";
}
return StringUtils.left(carId, 6).concat(StringUtils.removeStart(StringUtils.leftPad(StringUtils.right(carId, 4), StringUtils.length(carId), "*"), "******"));
}
/**
* [固定电话] 后四位,其他隐藏<例子:****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), "*");
}
/**
* [手机号码] 前三位,后四位,其他隐藏<例子:138******1234>
*
* @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, 4), 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, "*");
}
/**
* [电子邮箱] 邮箱前缀仅显示第一个字母,前缀其他隐藏,用星号代替,@及后面的地址显示<例子:g**@163.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), "*"), "******"));
}
/**
* [公司开户银行联号] 公司开户银行联行号,显示前两位,其他用星号隐藏,每位1个星号<例子:12********>
*
* @param code
* @return
*/
public static String cnapsCode(String code) {
if (StringUtils.isBlank(code)) {
return "";
}
return StringUtils.rightPad(StringUtils.left(code, 2), StringUtils.length(code), "*");
}
/**
* 只显示第一个汉字,其他隐藏为2个星号<例子:李**>
*
* @param fullName
* @param index 1 为第index位开始脱敏
* @return
*/
public static String left(String fullName,int index) {
if (StringUtils.isBlank(fullName)) {
return "";
}
String name = StringUtils.left(fullName, index);
return StringUtils.rightPad(name, StringUtils.length(fullName), "*");
}
/**
* 110****58,前面保留3位明文,后面保留2位明文
*
* @param name
* @param index 3
* @param end 2
* @return
*/
public static String around(String name,int index,int end) {
if (StringUtils.isBlank(name)) {
return "";
}
return StringUtils.left(name, index).concat(StringUtils.removeStart(StringUtils.leftPad(StringUtils.right(name, end), StringUtils.length(name), "*"), "***"));
}
/**
* 后四位,其他隐藏<例子:****1234>
*
* @param num
* @return
*/
public static String right(String num,int end) {
if (StringUtils.isBlank(num)) {
return "";
}
return StringUtils.leftPad(StringUtils.right(num, end), StringUtils.length(num), "*");
}
/**
* 手机号码前三后四脱敏
* @author yinxing
* @date 2019/12/16 10:44
* @param mobile 手机号
* @return java.lang.String
* @Copyright: Copyright (c) 2006 - 2019
* @Company: 万达信息股份有限公司
*/
public static String mobileEncrypt(String mobile) {
if (StringUtils.isEmpty(mobile) || (mobile.length() != 11)) {
return mobile;
}
return mobile.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
}
/**
* 身份证前三后四脱敏
*/
public static String idEncrypt(String idCard) {
if (StringUtils.isEmpty(idCard) || (idCard.length() < 8)) {
return idCard;
}
return idCard.replaceAll("(?<=\\w{3})\\w(?=\\w{4})", "*");
}
/**
* 护照前2后3位脱敏,护照一般为8或9位
*/
public static String idPassport(String id) {
if (StringUtils.isEmpty(id) || (id.length() < 8)) {
return id;
}
return id.substring(0, 2) + new String(new char[id.length() - 5]).replace("\0", "*") + id.substring(id.length() - 3);
}
/**
* 证件后几位脱敏
* @param id
* @param sensitiveSize
* @return
*/
public static String idPassport(String id, int sensitiveSize) {
if (StringUtils.isBlank(id)) {
return "";
}
int length = StringUtils.length(id);
return StringUtils.rightPad(StringUtils.left(id, length - sensitiveSize), length, "*");
}
}
02 创建自定义的脱敏注解 Desensitization
import java.lang.annotation.*;
/**
* 数据脱敏注解
* @author by LMGD
* @date 2020/1/10 13:02
* @description
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Desensitization {
DesensitizationType value();
/**
* 脱敏类型
* @author yx
*
*/
enum DesensitizationType{
/** 中文名 */
CHINESE_NAME,
/** 身份证号 */
ID_CARD,
/** 座机号 */
FIXED_PHONE,
/** 手机号 */
MOBILE_PHONE,
/** 地址 */
ADDRESS,
/** 电子邮件 */
EMAIL,
/** 银行卡 */
BANK_CARD,
/** 密码 */
PASSWORD,
/** 其它类型(当作不做处理) */
OTHER};
/**
* 脱敏类型字段
* @return
*/
DesensitizationType name() default DesensitizationType.OTHER;
/*判断注解是否生效的方法*/
String isEffictiveMethod() default "";
}
03 创建对对象脱敏处理的工具类 DesensitizationUtils
import java.lang.reflect.Field;
/**
* @author by LMGD
* @date 2020/1/14 17:35
* @description 数据脱敏的工具类
*/
public class DesensitizationUtils {
/**
* 加密数据
*/
public static Object encryptJavaBean(Object o) {
try {
Class<? extends Object> c = o.getClass();
// 获取所有属性值
Field[] fields = c.getDeclaredFields();
Object value = null;
for (Field f : fields) {
f.setAccessible(true);
// 获取属性上的注解
Desensitization annotation = f.getAnnotation(Desensitization.class);
//取出对象的属性值
value = f.get(o);
// 有此类注解 同时 当前遍历的属性值不能为空
if (annotation != null && String.class.equals(f.getGenericType()) && ObjectUtil.isNotEmpty(value)) {//注:经测试只有String类型才可以脱敏其他类型加了脱敏注解也无法脱敏
Desensitization.DesensitizationType type = annotation.value();
// 判断注解类型
switch (type) {
case ID_CARD:
//value不为空才调用value.toString()方法,否则报空指针;
f.set(o, SensitiveInfoUtils.idCard(value.toString()));
break;
case MOBILE_PHONE:// 手机号
f.set(o, SensitiveInfoUtils.mobilePhone(value.toString()));
break;
case CHINESE_NAME:// 用户名
f.set(o, SensitiveInfoUtils.chineseName(value.toString()));
break;
case ADDRESS:
f.set(o, SensitiveInfoUtils.address(value.toString(), 6));
break;
case EMAIL:
f.set(o, SensitiveInfoUtils.email(value.toString()));
break;
case OTHER:
default:
break;
}
}
}
return o;
} catch (Exception e) {
return o;
}
}
}
04 创建对象 OrderwebUser 并且添加自定义的脱敏注解
public class OrderwebUser implements java.io.Serializable {
/**
* 证件号码.
*/
@Desensitization(value = Desensitization.DesensitizationType.ID_CARD)
private String m_papersNum;
/**
* 用户真实姓名.
*/
@Desensitization(value = Desensitization.DesensitizationType.CHINESE_NAME)
private String m_userName;
/**
* 用户手机号码.
*/
@Desensitization(value = Desensitization.DesensitizationType.MOBILE_PHONE)
private String m_userPhone;
/**
* 用户住址.
*/
@Desensitization(value = Desensitization.DesensitizationType.ADDRESS)
private String m_userAdress;
/**
* 用户邮箱.
*/
@Desensitization(value = Desensitization.DesensitizationType.EMAIL)
private String m_userEmail;
public OrderwebUser() {
}
//省略 get/set方法
}
05 Junit测试
/**
* @author by LMGD
* @date 2020/1/6 16:20
* @description
*/
public class MyTest {
/**
* LMGD-测试注解式数据脱敏-对象脱敏
*/
@Test
public void test() {
OrderwebUser orderwebUser = new OrderwebUser();
orderwebUser.setPapersNum("122345666666669898");
orderwebUser.setUserPhone("12334567876");
orderwebUser.setUserName("LMGD");
orderwebUser.setUserEmail("101019999@qq.com");
orderwebUser.setUserAdress("湖南省长沙市xx区xxxxxxxxx");
//对象脱敏
DesensitizationUtils.encryptJavaBean(orderwebUser);//直接这样不用下面那行代码那样;输出的对象就是脱敏后的对象了
//orderwebUser = (OrderwebUser)DesensitizationUtils.encryptJavaBean(orderwebUser);//效果与上一行代码一样
System.out.println(orderwebUser);
System.out.println(orderwebUser.getUserPhone());
}
/**
* LMGD-测试注解式数据脱敏-集合脱敏
*/
@Test
public void test() {
OrderwebUser orderwebUser = new OrderwebUser();
orderwebUser.setPapersNum("122345666666669898");
orderwebUser.setUserPhone("12334567876");
orderwebUser.setUserName("LMGD");
orderwebUser.setUserEmail("101019999@qq.com");
orderwebUser.setUserAdress("湖南省长沙市xx区xxxxxxxxx");
List<OrderwebUser> list = new ArrayList<>();
list.add(orderwebUser);
//数据脱敏-集合脱敏
// DesensitizationUtils.encryptJavaBean(list.get(0));
//数据脱敏-集合脱敏
for(OrderwebUser user:list){
DesensitizationUtils.encryptJavaBean(user);
}
System.out.println(list.get(0));//取出的就是脱敏后的对象
}
/**
* Map 脱敏
* @注:不需要添加注解式脱敏
*/
@Test
public void testMap() {
Map<String, String> result =new HashMap<>();
result.put("name","LMGD");
result.put("cardId","122345666666669898");
result.put("phone","12121122222");
result = getOrderDetailInfoResult(result);
System.out.println("脱敏后的Map:"+result);
}
public Map<String, String> getOrderDetailInfoResult(Map<String, String> result) {
result.put("name", SensitiveInfoUtils.chineseName(result.get("patientName")));
result.put("cardId", SensitiveInfoUtils.idCard(result.get("patientCardId")));
result.put("phone", SensitiveInfoUtils.mobilePhone(result.get("phone")));
return result;
}
/**
* 不需要注解进行脱敏的方法
*/
@Test
public void Test() {
String address = SensitiveInfoUtils.address("湖南省长沙市xx区xxx", 6);
System.out.println(address);
}
/**
* 不需要注解就可以对list集合进行脱敏的方法
*/
public List<OrderwebUser> getList(List<OrderwebUser> list) {
int size = list.size();
OrderwebUser user = null;
for (int i = 0; i < size; i++) {
user = list.get(i);
user.setUserName(SensitiveInfoUtils.chineseName(user.getUserName()));
user.setPapersNum(SensitiveInfoUtils.idCard(user.getPapersNum()));
user.setUserPhone(SensitiveInfoUtils.mobilePhone(user.getUserPhone()));
user.setUserEmail(SensitiveInfoUtils.email(user.getUserEmail()));
user.setHealthCardNum(SensitiveInfoUtils.idCardNum(user.getHealthCardNum()));
}
return list;
}
}
注:要是这篇文章有帮助到你 ,动动你的大拇指 点个赞 哈哈哈哈哈 ;快过年啦 有缘看到这篇文章的小伙伴 祝你新年快乐哈!