数据脱敏:保护隐私,刻不容缓!(附带脱敏工具)

在这里插入图片描述

🌟我的其他文章也讲解的比较有趣😁,如果喜欢博主的讲解方式,可以多多支持一下,感谢🤗!

🌟了解 SpringBoot 自动装配原理请看: SpringBoot自动装配原理详解!结合源代码讲解!

其他优质专栏: 【🎇SpringBoot】【🎉多线程】【🎨Redis】【✨设计模式专栏已完结)】…等

如果喜欢作者的讲解方式,可以点赞收藏加关注,你的支持就是我的动力
✨更多文章请看个人主页: 码熔burning

一、数据脱敏的定义

数据脱敏,也称为数据屏蔽、数据变形,是指对某些敏感数据通过脱敏规则进行转换,使其不再是原始的、真实的敏感数据,从而保护数据的安全性。简单来说,就是把一些敏感信息“伪装”起来 🎭,让别人看不到真实的内容,但还能保证数据在一定程度上可用。

为什么要脱敏?

  • 保护隐私 🔒:避免个人信息泄露,如姓名、身份证号、手机号、银行卡号等。
  • 数据安全 🛡️:防止内部人员或外部攻击者获取敏感数据,造成损失。
  • 合规要求 ✅:满足法律法规对数据保护的要求,如《网络安全法》、《个人信息保护法》等。
  • 测试环境 🧪:在测试、开发环境中,使用脱敏后的数据,避免真实数据泄露。

二、常用的脱敏规则

脱敏规则有很多种,选择哪种取决于数据的类型、敏感程度和业务需求。下面是一些常见的规则:

  1. 替换(Replacement): 用固定的字符或字符串替换原始数据。

    • 例如:将手机号中间四位替换为****,变成138****1234
  2. 遮蔽(Masking): 用特定的字符遮盖部分数据。

    • 例如:将身份证号的前几位和后几位保留,中间用*遮盖。
  3. 截断(Truncation): 删除部分数据。

    • 例如:只显示用户名的前几个字符。
  4. 加密(Encryption): 使用加密算法对数据进行加密,需要时再解密。

    • 例如:对银行卡号进行加密存储。
  5. 哈希(Hashing): 使用哈希算法将数据转换为不可逆的哈希值。

    • 例如:对密码进行哈希存储。
  6. 随机化(Randomization): 用随机生成的数据替换原始数据。

    • 例如:随机生成一个年龄或地址。
  7. 偏移(Shifting): 对数值型数据进行偏移。

    • 例如:将所有年龄都加上或减去一个固定的值。
  8. 泛化(Generalization): 将数据归类到更广泛的类别。

    • 例如:将具体的职业替换为职业类别(如:程序员 -> IT从业者)。
  9. 空值化(Nulling): 将数据设置为空值。

    • 例如:如果某些数据不需要使用,可以直接设置为空。

三、常见脱敏工具及代码实例

下面介绍一些常用的Java脱敏工具,并给出代码示例。

  1. Hutool

    Hutool是一个Java工具包,提供了很多实用的工具类,包括脱敏工具。

    import cn.hutool.core.util.DesensitizedUtil;
    
    public class HutoolExample {
        public static void main(String[] args) {
            String mobilePhone = "13812345678";
            String idCard = "320101199001011234";
            String address = "北京市海淀区中关村大街1号";
    
            String desensitizedMobile = DesensitizedUtil.mobilePhone(mobilePhone);
            String desensitizedIdCard = DesensitizedUtil.idCardNum(idCard, 3, 4); // 保留前3位和后4位
            String desensitizedAddress = DesensitizedUtil.address(address, 3); // 保留前3位
    
            System.out.println("脱敏后的手机号: " + desensitizedMobile); // 输出:138****5678
            System.out.println("脱敏后的身份证号: " + desensitizedIdCard); // 输出:320***********1234
            System.out.println("脱敏后的地址: " + desensitizedAddress); // 输出:北京市海淀区***
        }
    }
    

    解释: Hutool就像一个工具箱 🧰,里面有各种各样的工具,其中有一个专门用来给数据“化妆”的工具 💄,可以轻松地把手机号、身份证号、地址等敏感信息处理一下。

  2. ShardingSphere

    ShardingSphere是一个分布式数据库中间件,它也提供了数据脱敏的功能,主要用于数据库层面的脱敏。 ShardingSphere的脱敏功能通常配置在数据分片规则中,可以对查询结果进行脱敏。

    注意: ShardingSphere的脱敏配置比较复杂,需要定义脱敏算法,并将其应用到特定的表和列上。 以下是一个简化的概念示例,实际配置需要参考ShardingSphere的官方文档。

    <!-- ShardingSphere脱敏配置 (简化示例) -->
    <bean id="shardingRuleConfiguration" class="org.apache.shardingsphere.sharding.api.config.ShardingRuleConfiguration">
        <property name="tables">
            <map>
                <entry key="t_user">
                    <bean class="org.apache.shardingsphere.sharding.api.config.rule.ShardingTableRuleConfiguration">
                        <property name="logicTable" value="t_user"/>
                        <property name="actualDataNodes" value="ds0.t_user,ds1.t_user"/>
                        <property name="tableStrategyConfig">
                            <bean class="org.apache.shardingsphere.sharding.api.config.strategy.StandardShardingStrategyConfiguration">
                                <constructor-arg name="shardingColumn" value="user_id"/>
                                <constructor-arg name="shardingAlgorithmName" value="inlineTableShardingAlgorithm"/>
                            </bean>
                        </property>
                        <property name="keyGeneratorConfig">
                            <bean class="org.apache.shardingsphere.sharding.api.config.KeyGeneratorConfiguration">
                                <constructor-arg name="type" value="SNOWFLAKE"/>
                                <constructor-arg name="column" value="user_id"/>
                            </bean>
                        </property>
                        <property name="encryptRule">
                            <bean class="org.apache.shardingsphere.encrypt.api.config.EncryptRuleConfiguration">
                                <property name="encryptors">
                                    <map>
                                        <entry key="mobile_encryptor">
                                            <bean class="org.apache.shardingsphere.encrypt.api.config.EncryptorRuleConfiguration">
                                                <constructor-arg name="type" value="AES"/>
                                                <constructor-arg name="properties">
                                                    <map>
                                                        <entry key="aes.key.value" value="your_aes_key"/>
                                                    </map>
                                                </constructor-arg>
                                            </bean>
                                        </entry>
                                    </map>
                                </property>
                                <property name="tables">
                                    <map>
                                        <entry key="t_user">
                                            <bean class="org.apache.shardingsphere.encrypt.api.config.EncryptTableRuleConfiguration">
                                                <property name="columns">
                                                    <map>
                                                        <entry key="mobile">
                                                            <bean class="org.apache.shardingsphere.encrypt.api.config.EncryptColumnRuleConfiguration">
                                                                <constructor-arg name="cipherColumn" value="mobile_cipher"/>
                                                                <constructor-arg name="encryptorName" value="mobile_encryptor"/>
                                                            </bean>
                                                        </entry>
                                                    </map>
                                                </property>
                                            </bean>
                                        </entry>
                                    </map>
                                </property>
                            </bean>
                        </property>
                    </bean>
                </entry>
            </map>
        </property>
        <property name="defaultDatabaseStrategyConfig">
            <bean class="org.apache.shardingsphere.sharding.api.config.strategy.StandardShardingStrategyConfiguration">
                <constructor-arg name="shardingColumn" value="database_id"/>
                <constructor-arg name="shardingAlgorithmName" value="inlineDatabaseShardingAlgorithm"/>
            </bean>
        </property>
        <property name="shardingAlgorithms">
            <map>
                <entry key="inlineTableShardingAlgorithm">
                    <bean class="org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingAlgorithm">
                        <property name="expression" value="t_user_${user_id % 2}"/>
                    </bean>
                </entry>
                <entry key="inlineDatabaseShardingAlgorithm">
                    <bean class="org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingAlgorithm">
                        <property name="expression" value="ds${database_id % 2}"/>
                    </bean>
                </entry>
            </map>
        </property>
    </bean>
    

    解释: ShardingSphere就像一个数据库的“管家” 🤵,它可以把数据分到不同的地方存储,还能在别人访问数据的时候,自动把敏感信息“处理”一下,比如加密或者替换掉。 配置比较复杂 ⚙️,需要告诉它哪些数据需要脱敏,用什么方法脱敏。

  3. Fastjson

    Fastjson是阿里巴巴开源的JSON处理库,虽然它本身没有直接的脱敏功能,但可以通过自定义序列化器来实现脱敏。

    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.annotation.JSONField;
    import com.alibaba.fastjson.serializer.ValueFilter;
    
    public class FastjsonExample {
    
        public static class User {
            private String name;
            @JSONField(serializeUsing = MobilePhoneDesensitization.class)
            private String mobilePhone;
            private String address;
    
            public User(String name, String mobilePhone, String address) {
                this.name = name;
                this.mobilePhone = mobilePhone;
                this.address = address;
            }
    
            public String getName() {
                return name;
            }
    
            public String getMobilePhone() {
                return mobilePhone;
            }
    
            public String getAddress() {
                return address;
            }
        }
    
        // 自定义序列化器
        public static class MobilePhoneDesensitization implements ValueFilter {
            @Override
            public Object process(Object object, String name, Object value) {
                if ("mobilePhone".equals(name) && value instanceof String) {
                    String mobile = (String) value;
                    if (mobile.length() == 11) {
                        return mobile.substring(0, 3) + "****" + mobile.substring(7);
                    }
                }
                return value;
            }
        }
    
        public static void main(String[] args) {
            User user = new User("张三", "13812345678", "北京市海淀区");
            String json = JSON.toJSONString(user);
            System.out.println(json); // 输出:{"address":"北京市海淀区","mobilePhone":"138****5678","name":"张三"}
    
            // 使用ValueFilter进行全局脱敏
            ValueFilter filter = (Object object, String name, Object value) -> {
                if ("address".equals(name) && value instanceof String) {
                    return "***"; // 对所有address字段进行脱敏
                }
                return value;
            };
    
            String jsonWithFilter = JSON.toJSONString(user, filter);
            System.out.println(jsonWithFilter); // 输出:{"address":"***","mobilePhone":"138****5678","name":"张三"}
        }
    }
    

    解释: Fastjson就像一个翻译器 🗣️,可以把Java对象翻译成JSON字符串。我们可以告诉它,在翻译手机号的时候,要先给手机号“化个妆” 💄,把中间几位换成星星 ⭐。

  4. MyBatis-Flex

    MyBatis-Flex 是一个优雅的 MyBatis 增强框架,它提供了灵活的配置方式,可以方便地实现数据脱敏。

    import com.mybatisflex.annotation.Column;
    import com.mybatisflex.annotation.Table;
    import com.mybatisflex.core.handler.AbstractTypeHandler;
    import com.mybatisflex.core.query.QueryWrapper;
    import com.mybatisflex.mapper.BaseMapper;
    import org.apache.ibatis.type.JdbcType;
    import org.apache.ibatis.type.MappedTypes;
    
    import java.sql.CallableStatement;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    // 自定义 TypeHandler
    @MappedTypes(String.class)
    public class MobilePhoneTypeHandler extends AbstractTypeHandler<String> {
    
        @Override
        public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
            // 保存到数据库时,可以进行加密等处理
            ps.setString(i, parameter);
        }
    
        @Override
        public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
            String mobile = rs.getString(columnName);
            if (mobile != null && mobile.length() == 11) {
                return mobile.substring(0, 3) + "****" + mobile.substring(7);
            }
            return mobile;
        }
    
        @Override
        public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
            String mobile = rs.getString(columnIndex);
            if (mobile != null && mobile.length() == 11) {
                return mobile.substring(0, 3) + "****" + mobile.substring(7);
            }
            return mobile;
        }
    
        @Override
        public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
            String mobile = cs.getString(columnIndex);
            if (mobile != null && mobile.length() == 11) {
                return mobile.substring(0, 3) + "****" + mobile.substring(7);
            }
            return mobile;
        }
    }
    
    // 实体类
    @Table("tb_user")
    public static class User {
        private Long id;
        private String name;
    
        @Column(typeHandler = MobilePhoneTypeHandler.class)
        private String mobilePhone;
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getMobilePhone() {
            return mobilePhone;
        }
    
        public void setMobilePhone(String mobilePhone) {
            this.mobilePhone = mobilePhone;
        }
    }
    
    // Mapper 接口
    public interface UserMapper extends BaseMapper<User> {
    }
    
    // 使用示例
    public class MyBatisFlexExample {
        public static void main(String[] args) {
            // 假设已经配置好了 MyBatis-Flex
            UserMapper userMapper = null; // 获取 UserMapper 实例
    
            // 查询用户
            User user = userMapper.selectOneById(1L);
            System.out.println("脱敏后的手机号: " + user.getMobilePhone());
    
            // 插入用户
            User newUser = new User();
            newUser.setName("李四");
            newUser.setMobilePhone("13912345678");
            userMapper.insert(newUser);
        }
    }
    

    解释: MyBatis-Flex 就像一个数据库的“翻译官” 🧑‍🏫,它可以把数据库里的数据翻译成Java对象。我们可以自定义一个“翻译规则” 📜,告诉它在翻译手机号的时候,要先给手机号“化个妆” 💄,把中间几位换成星星 ⭐。

  5. Mybatis-Mate

    Mybatis-Mate 是一款基于 MyBatis 的代码生成器和增强工具,它也支持自定义 TypeHandler 来实现数据脱敏。

    import net.dreamlu.mica.mybatis.typehandler.AbstractTypeHandler;
    import org.apache.ibatis.type.JdbcType;
    import org.apache.ibatis.type.MappedTypes;
    
    import java.sql.CallableStatement;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    // 自定义 TypeHandler
    @MappedTypes(String.class)
    public class MobilePhoneTypeHandler extends AbstractTypeHandler<String> {
    
        @Override
        public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
            // 保存到数据库时,可以进行加密等处理
            ps.setString(i, parameter);
        }
    
        @Override
        public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
            String mobile = rs.getString(columnName);
            if (mobile != null && mobile.length() == 11) {
                return mobile.substring(0, 3) + "****" + mobile.substring(7);
            }
            return mobile;
        }
    
        @Override
        public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
            String mobile = rs.getString(columnIndex);
            if (mobile != null && mobile.length() == 11) {
                return mobile.substring(0, 3) + "****" + mobile.substring(7);
            }
            return mobile;
        }
    
        @Override
        public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
            String mobile = cs.getString(columnIndex);
            if (mobile != null && mobile.length() == 11) {
                return mobile.substring(0, 3) + "****" + mobile.substring(7);
            }
            return mobile;
        }
    }
    
    // 实体类
    public class User {
        private Long id;
        private String name;
        private String mobilePhone;
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getMobilePhone() {
            return mobilePhone;
        }
    
        public void setMobilePhone(String mobilePhone) {
            this.mobilePhone = mobilePhone;
        }
    }
    
    // 使用示例 (假设已经配置好了 Mybatis-Mate)
    public class MybatisMateExample {
        public static void main(String[] args) {
            // 获取 User 对象
            User user = null; // 从数据库查询得到 User 对象
    
            // 在获取 mobilePhone 属性时,会自动进行脱敏
            String desensitizedMobile = user.getMobilePhone();
            System.out.println("脱敏后的手机号: " + desensitizedMobile);
        }
    }
    

    解释: Mybatis-Mate 也是一个数据库的“翻译官” 🧑‍🏫,和 MyBatis-Flex 类似,它可以把数据库里的数据翻译成Java对象。我们可以自定义一个“翻译规则” 📜,告诉它在翻译手机号的时候,要先给手机号“化个妆” 💄,把中间几位换成星星 ⭐。

完整的Hutool实例,包含依赖和测试:

<!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.23</version>
</dependency>
import cn.hutool.core.util.DesensitizedUtil;

public class HutoolExample {
    public static void main(String[] args) {
        String mobilePhone = "13812345678";
        String idCard = "320101199001011234";
        String address = "北京市海淀区中关村大街1号";
        String email = "test@example.com";
        String bankCard = "6222020000000000";

        String desensitizedMobile = DesensitizedUtil.mobilePhone(mobilePhone);
        String desensitizedIdCard = DesensitizedUtil.idCardNum(idCard, 3, 4); // 保留前3位和后4位
        String desensitizedAddress = DesensitizedUtil.address(address, 3); // 保留前3位
        String desensitizedEmail = DesensitizedUtil.email(email);
        String desensitizedBankCard = DesensitizedUtil.bankCard(bankCard);

        System.out.println("脱敏后的手机号: " + desensitizedMobile); // 输出:138****5678
        System.out.println("脱敏后的身份证号: " + desensitizedIdCard); // 输出:320***********1234
        System.out.println("脱敏后的地址: " + desensitizedAddress); // 输出:北京市海淀区***
        System.out.println("脱敏后的邮箱: " + desensitizedEmail); // 输出:t**@example.com
        System.out.println("脱敏后的银行卡号: " + desensitizedBankCard); // 输出:622202********0000
    }
}

四、总结

  • Hutool 适合在代码中对单个数据进行脱敏,使用简单方便 🚀。
  • ShardingSphere 适合在数据库层面进行脱敏,可以对查询结果进行脱敏,但配置比较复杂 ⚙️。
  • Fastjson 可以通过自定义序列化器来实现脱敏,适合在JSON序列化时进行脱敏 💡。
  • MyBatis-Flex 和 Mybatis-Mate 可以通过自定义 TypeHandler 来实现数据库字段的脱敏,适合在数据访问层进行脱敏 📚。

选择哪种工具取决于你的具体需求和使用场景 🤔。 希望篇文章能够帮助你理解数据脱敏的概念和常用工具 🎉。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值