注解式数据脱敏

什么是脱敏

数据脱敏是指对某些敏感信息通过脱敏规则进行数据的变形,实现敏感隐私数据的可靠保护。在涉及客户安全数据或者一些商业性敏感数据的情况下,在不违反系统规则条件下,对真实数据进行改造并提供测试使用,如身份证号、手机号、卡号、客户号等个人信息都需要进行数据脱敏。

如何使用注解式数据脱敏

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;
    }
}

注:要是这篇文章有帮助到你 ,动动你的大拇指 点个赞  哈哈哈哈哈 ;快过年啦 有缘看到这篇文章的小伙伴 祝你新年快乐哈!

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值