java自定义注解实现数据脱敏

1、自定义序列化

复制代码
package com.sxsoft.admin.entity.customEntity;

import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.DesensitizedUtil;
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 com.sxsoft.admin.Component.DataMasking;
import com.sxsoft.admin.enums.DataMaskingType;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;

import java.io.IOException;
import java.util.Objects;

/**
 * @program: sxsoft_expert
 * @ClassName DataMaskingSerialize
 * @description: 自定义序列化类
 * @author: 黄涛
 * @create: 2023-10-25 07:56
 * @Version 1.0
 **/
@AllArgsConstructor
@NoArgsConstructor
public class DataMaskingSerialize extends JsonSerializer implements ContextualSerializer {

    private DataMaskingType type;

    private Integer start;

    private Integer end;

    @Override
    public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        String value = (String) o;
        switch (type) {
            //userId
            case USER_ID:
                jsonGenerator.writeString(String.valueOf(DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.USER_ID)));
                break;
            //中文名
            case CHINESE_NAME:
                jsonGenerator.writeString(DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.CHINESE_NAME));
                break;
            //身份证号
            case ID_CARD:
                jsonGenerator.writeString(DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.ID_CARD));
                break;
            //座机
            case FIXED_PHONE:
                jsonGenerator.writeString(DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.FIXED_PHONE));
                break;
            //手机号
            case MOBILE_PHONE:
                jsonGenerator.writeString(DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.MOBILE_PHONE));
                break;
            //地址
            case ADDRESS:
                jsonGenerator.writeString(DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.ADDRESS));
                break;
            //邮箱
            case EMAIL:
                jsonGenerator.writeString(DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.EMAIL));
                break;
            case BANK_CARD:
                jsonGenerator.writeString(DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.BANK_CARD));
                break;
            //密码
            case PASSWORD:
                jsonGenerator.writeString(DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.PASSWORD));
                break;
            //中国大陆车牌号
            case CAR_LICENSE:
                jsonGenerator.writeString(DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.CAR_LICENSE));
                break;
//            case IPV4:
//                jsonGenerator.writeString(DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.IPV4));
//                break;
//            case IPV6:
//                jsonGenerator.writeString(DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.IPV6));
//                break;
            //自定义
            case CUSTOM:
                jsonGenerator.writeString(CharSequenceUtil.hide(value, start, end));
                break;
            default:
                break;
        }
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {
        if (Objects.nonNull(beanProperty)) {
            //判断是否为string类型
            if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) {
                DataMasking anno = beanProperty.getAnnotation(DataMasking.class);
                if (Objects.isNull(anno)) {
                    anno = beanProperty.getContextAnnotation(DataMasking.class);
                }
                if (Objects.nonNull(anno)) {
                    return new DataMaskingSerialize(anno.type(), anno.start(), anno.end());
                }
            }
            return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
        }
        return serializerProvider.findNullValueSerializer(null);
    }
}
复制代码

2、自定义枚举

复制代码
package com.sxsoft.admin.enums;

/**
 * @program: sxsoft_expert
 * @ClassName DataMaskingType
 * @description:脱敏枚举
 * @author: 黄涛
 * @create: 2023-10-25 07:54
 * @Version 1.0
 **/
public enum DataMaskingType {

    /**
     * 用户ID
     */
    USER_ID,
    /**
     * 中文名
     */
    CHINESE_NAME,
    /**
     * 身份证号
     */
    ID_CARD,
    /**
     * 座机
     */
    FIXED_PHONE,
    /**
     * 手机号
     */
    MOBILE_PHONE,
    /**
     * 地址
     */
    ADDRESS,
    /**
     * 邮箱
     */
    EMAIL,
    /**
     * 密码
     */
    PASSWORD,
    /**
     * 中国大陆车牌号
     */
    CAR_LICENSE,
    /**
     * 银行卡号
     */
    BANK_CARD,
    /**
     * IPv4地址
     */
    IPV4,
    /**
     * IPv6地址
     */
    IPV6,
    /**
     * 自定义类型
     */
    CUSTOM;
}
复制代码

3、自定义注解

复制代码
package com.sxsoft.admin.Component;

import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.sxsoft.admin.entity.customEntity.DataMaskingSerialize;
import com.sxsoft.admin.enums.DataMaskingType;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * @program: sxsoft_expert
 * @ClassName DataMasking
 * @description: 数据脱敏自定义注解
 * @author: 黄涛
 * @create: 2023-10-25 07:55
 * @Version 1.0
 **/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = DataMaskingSerialize.class)
public @interface DataMasking {

    /**
     * 数据脱敏类型
     */
    DataMaskingType type() default DataMaskingType.CUSTOM;

    /**
     * 脱敏开始位置(包含)
     */
    int start() default 0;

    /**
     * 脱敏结束位置(不包含)
     */
    int end() default 0;

}
复制代码

4、测试实体

复制代码
package com.sxsoft.admin.entity.customEntity;


import com.sxsoft.admin.Component.DataMasking;
import com.sxsoft.admin.enums.DataMaskingType;
import lombok.*;
/**
 * @program: sxsoft_expert
 * @ClassName TestEntity
 * @description:
 * @author: 黄涛
 * @create: 2023-10-25 08:00
 * @Version 1.0
 **/
@Data
@Builder
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class TestEntity {

    @DataMasking(type = DataMaskingType.USER_ID)
    private Integer userId;

    @DataMasking(type = DataMaskingType.CHINESE_NAME)
    private String userName;

    @DataMasking(type = DataMaskingType.ADDRESS)
    private String address;

    @DataMasking(type = DataMaskingType.ID_CARD)
    private String idCard;

    @DataMasking(type = DataMaskingType.FIXED_PHONE)
    private String fixedPhone;

    @DataMasking(type = DataMaskingType.MOBILE_PHONE)
    private String mobilePhone;

    @DataMasking(type = DataMaskingType.EMAIL)
    private String email;

    @DataMasking(type = DataMaskingType.PASSWORD)
    private String password;

    @DataMasking(type = DataMaskingType.CAR_LICENSE)
    private String carLicense;

    @DataMasking(type = DataMaskingType.BANK_CARD)
    private String bankCard;

//    @DataMasking(type = DataMaskingType.IPV4)
//    private String ipv4;
//
//    @DataMasking(type = DataMaskingType.IPV6)
//    private String ipv6;

    @DataMasking(type = DataMaskingType.CUSTOM,start = 3,end = 9)
    private String custom;

    /**
     * 不进行数据脱敏的字段
     */
    private String noMask;


}
复制代码

5、使用

复制代码
 @RequestMapping(value="/test")
    public TestEntity test()  {

        //只能直接返回实体?
        TestEntity entity = TestEntity.builder()
                .userId(1234567890)
                .userName("张三")
                .password("12")
                .address("河南省郑州市中原区")
                .email("xxxx@xx.com")
                .fixedPhone("0838-5553792")
                .mobilePhone("13888888888")
                .carLicense("豫P3U253")
                .bankCard("1679374639283740")
                .idCard("412711223344556677")
                .custom("289073458794")
                .noMask("我是不需要数据脱敏的字段")
                .build();
        return entity;

    }
复制代码

 

问题:好像只有直接返回实体才能脱敏,如果要对返回结果封装要怎么处理??

posted on   五官一体即忢  阅读(852)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示