Jackson+自定义注解实现数据脱敏

在Web应用程序中,有些数据属于敏感数据,不能直接展示给前端,例如身份证号码、电话号码等。这时候就需要对数据进行脱敏处理。

自定义脱敏注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)  // 针对成员属性进行脱敏
@JacksonAnnotationsInside  // 表示和其他Jackson注解联合使用,如果缺少则无法执行数据脱敏流程
@JsonSerialize(using = DesensitizeJsonSerializer.class)  // 表明使用的序列化的类,定义在后面
public @interface Desensitize {
    /**
     * 对数据的脱敏策略
     *
     * @return 脱敏策略
     */
    DesensitizeStrategy strategy();

    enum DesensitizeStrategy {
        /**
         * 对用户名进行脱敏,基于正则表达式实现
         */
        NAME(s -> s.replaceAll("(\\S)\\S(\\S*)", "$1*$2")),

        /**
         * 对身份证进行脱敏
         */
        ID_CARD(s -> s.replaceAll("(\\d{4})\\d{10}(\\w{4})", "$1****$2")),

        /**
         * 对电话号码进行脱敏
         */
        PHONE(s -> s.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2")),

        /**
         * 对地址进行脱敏
         */
        ADDRESS(s -> s.replaceAll("(\\S{3})\\S{2}(\\S*)\\S{2}", "$1****$2****")),

        /**
         * 对密码进行脱敏,全部加密即可
         */
        PASSWORD(s -> "********");

        private final Function<String, String> desensitizeSerializer;

        DesensitizeStrategy(Function<String, String> desensitizeSerializer) {
            this.desensitizeSerializer = desensitizeSerializer;
        }

				// 用于后续获取脱敏的规则,实现脱敏
        public Function<String, String> desensitizeSerializer() {
            return desensitizeSerializer;
        }
    }
}

自定义JsonSerializer从而实现数据脱敏

public class DesensitizeJsonSerializer extends JsonSerializer<String> implements ContextualSerializer {
    private Desensitize.DesensitizeStrategy strategy;

    @Override
    public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
				// 在序列化时进行数据脱敏
        gen.writeString(strategy.desensitizeSerializer().apply(value));
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
        Desensitize annotation = property.getAnnotation(Desensitize.class);
        if (Objects.nonNull(annotation) && Objects.equals(String.class, property.getType().getRawClass())) {
            this.strategy = annotation.strategy();  // 主要代码在这里,获取脱敏的规则
            return this;
        }
        return prov.findValueSerializer(property.getType(), property);
    }
}

数据脱敏演示

  1. 实体类准备

    // Getter Setter Equals HashCode Constructor等无关注解省略
    // 脱敏的字段由电话号码,身份证号和密码
    
    @Entity  // 这是Spring Data Jpa中标注实体类的注解,实际开发过程可以使用别的ORM
    public class Employee {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
        @Column(nullable = false)
        private String name;
    
        @Column(nullable = false)
        @Desensitize(strategy = Desensitize.DesensitizeStrategy.PHONE)
        private String phone;
    
        @Column(nullable = false)
        private String email;
    
        @Column(nullable = false, unique = true)
        @Desensitize(strategy = Desensitize.DesensitizeStrategy.ID_CARD)
        private String identity;
    
        @Temporal(TemporalType.DATE)
        @Column(nullable = false)
        private Date birthday;
    
        /**
         * 员工的工号
         */
        @Column(nullable = false, unique = true)
        private String jobNumber;
    
        @Column(nullable = false)
        @Desensitize(strategy = Desensitize.DesensitizeStrategy.PASSWORD)
        private String password;
    
        @Column(nullable = false)
        private Boolean verified;
    }
    
  2. 数据演示(Id、出生日期、账号是否激活等无关字段省略)(相关字段采用Python Faker库随机生成,不包含他人真实信息)

    姓名密码电话号码电子邮箱身份证号工号
    芦畅123413625749433jing66@example.org37090219951023007320221390
    彭旭123418622101447qluo@example.net36082819900108105320223395
    张亮123413423600682xiulanzeng@example.net31011619401007472220221375
    马柳123413355470169qiang22@example.com34162219601130849820221973
    李丽华123415317475176xiuyinglei@example.org62020019700108701220222143
  3. 脱敏结果演示

    {
        "code": "00000",
        "message": "OK",
        "data": [
            {
                "id": "1",
                "name": "芦畅",
                "phone": "136****9433",
                "email": "jing66@example.org",
                "identity": "3709****0073",
                "birthday": "2004-12-29",
                "jobNumber": "20221390",
                "password": "********",
                "verified": false
            },
            {
                "id": "2",
                "name": "彭旭",
                "phone": "186****1447",
                "email": "qluo@example.net",
                "identity": "3608****1053",
                "birthday": "1983-12-04",
                "jobNumber": "20223395",
                "password": "********",
                "verified": false
            },
            {
                "id": "3",
                "name": "张亮",
                "phone": "134****0682",
                "email": "xiulanzeng@example.net",
                "identity": "3101****4722",
                "birthday": "1973-09-04",
                "jobNumber": "20221375",
                "password": "********",
                "verified": false
            },
            {
                "id": "4",
                "name": "马柳",
                "phone": "133****0169",
                "email": "qiang22@example.com",
                "identity": "3416****8498",
                "birthday": "2005-05-17",
                "jobNumber": "20221973",
                "password": "********",
                "verified": false
            },
            {
                "id": "5",
                "name": "李丽华",
                "phone": "153****5176",
                "email": "xiuyinglei@example.org",
                "identity": "6202****7012",
                "birthday": "1994-03-23",
                "jobNumber": "20222143",
                "password": "********",
                "verified": false
            }
        ]
    }
    

    可以看到,数据被成功脱敏

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

OriginCoding

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值