当前位置: 代码网 > it编程>编程语言>Java > SpringBoot实战:轻松实现接口数据脱敏

SpringBoot实战:轻松实现接口数据脱敏

2024年08月02日 Java 我要评论
接口数据脱敏是指在Web应用程序的API接口返回数据时,对包含敏感信息的字段进行处理,使其部分或全部信息被隐藏或替换,以防止敏感信息的泄露。这个过程通常不会改变数据的原始格式,而是通过特定的算法或规则,将敏感部分替换为特定字符(如星号*)或者保留部分信息。接下来,我们创建一个自定义注解/*** 用于标记字段需要进行脱敏处理的注解*//*** 脱敏类型*//*** 脱敏起始位置*//*** 脱敏结束位置*/然后,定义枚举类/*** 脱敏类型枚举类/*** 默认脱敏。


在这里插入图片描述

引言

一、接口数据脱敏概述

1.1 接口数据脱敏的定义

接口数据脱敏是指在web应用程序的api接口返回数据时,对包含敏感信息的字段进行处理,使其部分或全部信息被隐藏或替换,以防止敏感信息的泄露。这个过程通常不会改变数据的原始格式,而是通过特定的算法或规则,将敏感部分替换为特定字符(如星号*)或者保留部分信息。

1.2 接口数据脱敏的重要性

数据脱敏的重要性主要体现在以下几个方面:

  1. 保护用户隐私: 对于姓名、身份证号、手机号等个人敏感信息进行脱敏,可以有效保护用户隐私,防止信息被滥用。
  2. 遵守法律法规: 许多国家和地区都制定了严格的数据保护法规,如欧盟的gdpr和中国的《个人信息保护法》。实施数据脱敏有助于企业合规经营。
  3. 降低安全风险: 通过脱敏处理,即使数据不慎泄露,也能最大限度地减少敏感信息被盗用的风险。
  4. 支持数据共享: 在保护隐私的同时,脱敏数据仍然保留了一定的分析价值,有利于数据的安全共享和利用。

1.3 接口数据脱敏的实现方式

  1. 手动脱敏:在业务逻辑层直接对敏感数据进行处理。这种方式灵活但容易遗漏,且代码重复率高。

  2. aop(面向切面编程):通过切面拦截返回数据,统一处理敏感字段。这种方式可以集中管理脱敏逻辑,但可能影响性能。

  3. 自定义序列化器:利用json序列化框架(如jackson)的自定义序列化器来处理敏感字段。这种方式性能较好,且与业务逻辑解耦。

  4. 注解+反射:通过自定义注解标记需要脱敏的字段,然后利用反射机制在运行时进行脱敏处理。这种方式使用简单,易于维护。

本文将重点介绍如何结合自定义注解和hutool工具类来实现接口数据脱敏。

二、开发环境

  • jdk版本:jdk 17
  • spring boot版本:spring boot 3.2.2
  • 构建工具:maven

三、实现接口返回数据脱敏

3.1 添加依赖

首先在 pom.xml 文件中添加必要的依赖:

    <!-- hutool工具包 -->    
<dependency>
        <groupid>cn.hutool</groupid>
        <artifactid>hutool-all</artifactid>
        <version>5.8.25</version>
    </dependency>
    <!-- jackson依赖 -->
    <dependency>
        <groupid>com.fasterxml.jackson.core</groupid>
        <artifactid>jackson-databind</artifactid>
        <version>2.9.2</version>
    </dependency>

3.2 创建自定义注解

接下来,我们创建一个自定义注解 @desensitize

/**
 * 用于标记字段需要进行脱敏处理的注解
 *
 * @author shijun
 * @date 2024/07/09
 */
@retention(retentionpolicy.runtime)
@target(elementtype.field)
@jacksonannotationsinside
@jsonserialize(using = desensitizeserializer.class)
public @interface desensitize {

    /**
     * 脱敏类型
     */
    desensitizetype type() default desensitizetype.default;

    /**
     * 脱敏起始位置
     */
    int startinclude() default 0;

    /**
     * 脱敏结束位置
     */
    int endexclude() default 0;
    
}

3.3 定义脱敏枚举类

然后,定义枚举类 desensitizetype 来定义字段的脱敏类型:

/**
 * 脱敏类型枚举类
 */
public enum desensitizetype {

    /**
     * 默认脱敏
     */
    default,
    /**
     * 自定义脱敏
     */
    custom_rule,
    /**
     * 手机号脱敏
     */
    phone,
    /**
     * 电子邮件脱敏
     */
    email,
    /**
     * 身份证号脱敏
     */
    id_card,
    /**
     * 银行卡号脱敏
     */
    bank_card,
    /**
     * 地址脱敏
     */
    address,
    /**
     * 中文姓名脱敏
     */
    chinese_name,
    /**
     * 密码脱敏
     */
    password,
}

3.4 创建自定义序列化类

/**
 * 脱敏序列化器,用于在序列化字符串时根据不同的脱敏类型进行数据脱敏。
 *
 * @author shijun
 * @date 2024/07/08
 */
public class desensitizeserializer extends jsonserializer<string> implements contextualserializer {

    /**
     * 脱敏类型,默认为default
     */
    private desensitizetype type;
    /**
     * 脱敏起始位置
     */
    private int startinclude;
    /**
     * 脱敏结束位置
     */
    private int endexclude;

    public desensitizeserializer() {
        this.type = desensitizetype.default;
    }


    public desensitizeserializer(desensitizetype type) {
        this.type = type;
    }

    /**
     * 序列化字符串时调用,根据脱敏类型对字符串进行相应的脱敏处理。
     *
     * @param value       待序列化的字符串
     * @param gen         json生成器,用于写入处理后的字符串
     * @param serializers 序列化器提供者,用于获取其他序列化器
     * @throws ioexception 如果序列化过程中发生i/o错误
     */
    @override
    public void serialize(string value, jsongenerator gen, serializerprovider serializers) throws ioexception {
        switch (type) {
            case custom_rule:
                // 这里是对字符串的startinclude到endexclude字段进行隐藏处理,如果想要实现两端保留,可以考虑使用strutil的replace方法
                gen.writestring(strutil.hide(value, startinclude, endexclude));
                break;
            case phone:
                gen.writestring(desensitizedutil.mobilephone(value));
                break;
            case email:
                gen.writestring(desensitizedutil.email(value));
                break;
            case id_card:
                gen.writestring(desensitizedutil.idcardnum(value, 1, 2));
                break;
            case bank_card:
                gen.writestring(desensitizedutil.bankcard(value));
                break;
            case address:
                gen.writestring(desensitizedutil.address(value, 8));
                break;
            case chinese_name:
                gen.writestring(desensitizedutil.chinesename(value));
                break;
            case password:
                gen.writestring(desensitizedutil.password(value));
                break;
            default:
                gen.writestring(value);
                break;
        }
    }

    /**
     * 根据上下文信息创建自定义的序列化器,用于处理带有@desensitize注解的属性。
     *
     * @param prov     序列化器提供者,用于获取其他序列化器
     * @param property 当前属性的信息,用于获取注解和属性类型
     * @return 自定义的序列化器实例
     */
    @override
    public jsonserializer<?> createcontextual(serializerprovider prov, beanproperty property) {
        if (property != null) {
            desensitize annotation = property.getannotation(desensitize.class);
            if (annotation != null) {
                this.type = annotation.type();
                if (annotation.type() == desensitizetype.custom_rule) {
                    this.startinclude = annotation.startinclude();
                    this.endexclude = annotation.endexclude();
                }
            }
        }
        return this;
    }

}

四、测试

4.1 编写测试代码

  1. 编写实体类
@data
public class userdto {

    /**
     * 用户姓名
     */
    @desensitize(type = desensitizetype.chinese_name)
    private string name;

    /**
     * 用户手机号
     */
    @desensitize(type = desensitizetype.phone)
    private string phonenumber;

    /**
     * 用户电子邮件地址
     */
    @desensitize(type = desensitizetype.email)
    private string email;

    /**
     * 用户密码
     */
    @desensitize(type = desensitizetype.password)
    private string password;

    /**
     * 用户身份证号码
     */
    @desensitize(type = desensitizetype.id_card)
    private string idcard;

    /**
     * 用户银行卡号
     */
    @desensitize(type = desensitizetype.bank_card)
    private string bankcard;

    /**
     * 用户地址
     */
    @desensitize(type = desensitizetype.address)
    private string address;

    /**
     * 游戏名称
     */
    @desensitize(type = desensitizetype.custom_rule, startinclude = 2, endexclude = 6)
    private string gamename;
}

  1. 编写测试接口
@restcontroller
@requestmapping("/test")
public class testcontroller {
    
    @getmapping("/desensitize")
    public userdto getuser() {
        userdto userdto = new userdto();
        userdto.setname("孙大圣");
        userdto.setemail("shijun@163.com");
        userdto.setphonenumber("12345678901");
        userdto.setpassword("123456");
        userdto.setaddress("辽宁省盘锦市兴隆台区红村乡441号");
        userdto.setidcard("447465200912089605");
        userdto.setbankcard("6217000000000000000");
        userdto.setgamename("超级无敌大铁锤");
        return userdto;
    }

}

4.2 测试

image-20240709170909054

五、总结

在本文中,我们探讨了在springboot应用程序中实现数据脱敏的重要性,并提出了通过自定义注解结合hutool脱敏工具类实现数据脱敏的解决方案。通过这个方案,我们能够有效地对敏感数据进行脱敏处理,从而保护用户隐私和数据安全,希望对大家有所帮助😊。

在这里插入图片描述

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com