• SpringBoot进阶教程(七十五)数据脱敏


    v博客前言

    无论对于什么业务来说,用户数据信息的安全性无疑都是非常重要的。尤其是在数字经济大火背景下,数据的安全性就显得更加重要。数据脱敏可以分为两个部分,一个是DB层面,防止DB数据泄露,暴露用户信息;一个是接口层面,有些UI展示需要数据脱敏,防止用户信息被人刷走了。

    v需求背景

    DB层面的脱敏今天先不讲,今天先讲讲依赖于注解的接口层面的数据脱敏,接口层面的脱敏可能最原始和简单的方法就是在每个controller输出数据时,硬性处理。但是这么做的方案,如果后续脱敏规则改了,那需要改的地方就太多了,而且很容易有遗漏的地方,造成全站脱敏规则不统一的情况。所以我们建议的是用注解的方式,可插拔性更好,随时可以更改规则,更加的灵活。

    我们今天接到的需求是这样的:

    页面或者接口层面的脱敏,大多也是围绕用户手机号啊、真实姓名或者地址等等展开的。

    v架构设计

    2.1 脱敏字段枚举:SensitivityEnum

    这里定义一个敏感字段的枚举,并设定各个字段的脱敏策略。

    复制代码
    /**
     * @Author tou tou
     * @Date 2023/1/15
     * @Des 脱敏类型及策略,不同的字段类型适配不同的策略
     */
    public enum SensitivityEnum {
        /**
         * 用户名
         */
        USERNAME(s -> s.replaceAll("\\S*(\\S)", "***$1")),
        /**
         * 身份证
         */
        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****"));
    
    
        private final Function desensitizer;
    
        SensitivityEnum(Function desensitizer) {
            this.desensitizer = desensitizer;
        }
    
        public Function desensitizer() {
            return desensitizer;
        }
    }
    复制代码
    2.2 创建自定义隐私注解:Sensitivity

    都说了,我们使用的是注解的方式脱敏,所以是需要声明一个脱敏注解的,需要用到的地方,按需声明注解即可。非常方便。

    复制代码
    /**
     * @Author tou tou
     * @Date 2023/1/15
     * @Des
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.FIELD)
    @JacksonAnnotationsInside
    @JsonSerialize(using = SensitivitySerializer.class)
    public @interface Sensitivity {
        SensitivityEnum strategy();
    }
    复制代码
    2.3 创建序列化类:SensitivitySerializer
    复制代码
    /**
     * @Author tou tou
     * @Date 2023/1/15
     * @Des
     */
    public class SensitivitySerializer extends JsonSerializer implements ContextualSerializer {
        private SensitivityEnum sensitivityEnum;
    
        @Override
        public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
            gen.writeString(sensitivityEnum.desensitizer().apply(value));
        }
    
        @Override
        public JsonSerializer createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
    
            Sensitivity annotation = property.getAnnotation(Sensitivity.class);
            if (Objects.nonNull(annotation)&&Objects.equals(String.class, property.getType().getRawClass())) {
                this.sensitivityEnum = annotation.strategy();
                return this;
            }
    
            return prov.findValueSerializer(property.getType(), property);
        }
    }
    复制代码
    2.4 使用了@Sensitivity注解的实体类
    复制代码
    public class UserAccountVO {
        private Integer id;
    
        @Sensitivity(strategy = SensitivityEnum.USERNAME)
        private String username;
    
        private Integer age;
    
        @Sensitivity(strategy = SensitivityEnum.PHONE)
        private String tel;
    
        private String email;
    
        private String account;
    }
    复制代码
    2.5 插入mysql测试数据
    复制代码
    create table useraccount
    (
    id INT(11),
    username NVARCHAR(25),
    age INT(11),
    phone bigint,
    email VARCHAR(80),
    account VARCHAR(20),
    pwd VARCHAR(20)
    );
    
    select * from useraccount;
    insert into useraccount values(1,'张老三', 22, 13555551111,'13555551111@126.com','z13555551111', '13555551111');
    复制代码
    2.6 测试接口
    复制代码
    /**
     * @author toutou
     * @date by 2019/07
     */
    @RestController
    public class UserController {
    
        @Autowired
        UserAccountService userAccountService;
        
        @GetMapping("/user/getuser")
        public Result getUserAccountById(@RequestParam("uid") int id){
            UserAccountVO user = userAccountService.getUserAccountById(id);
            if(user != null){
                return Result.setSuccessResult(user);
            }else{
                return Result.setErrorResult(404, "用户不存在");
            }
        }
    }
    复制代码

    v运行效果

    SpringBoot进阶教程(七十五)数据脱敏

    v源码地址

    https://github.com/toutouge/javademosecond/tree/master/hellolearn

    您可以考虑给头头来个小小的打赏以资鼓励,您的肯定将是我最大的动力。thx.

    微信打赏

    微信账号 i7toutou

    支付宝打赏

    支付宝账号 datou431@qq.com


    作  者:请叫我头头哥
    出  处:http://www.cnblogs.com/toutou/
    关于作者:专注于基础平台的项目开发。如有问题或建议,请多多赐教!
    版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
    特此声明:所有评论和私信都会在第一时间回复。也欢迎园子的大大们指正错误,共同进步。或者直接私信
    声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是作者坚持原创和持续写作的最大动力!

  • 相关阅读:
    《Kubernetes部署篇:Ubuntu20.04基于containerd二进制部署K8S 1.25.14集群(多主多从)》
    华为云文件上传(单个上传和分段上传)
    运维:k8s常用命令大全
    分享99个小清新PPT模板,总有一款适合您
    Android SystemServer进程解析
    【MySQL】 B+ 树存储的原理
    Uniapp 动态修改状态栏、导航栏背景色、字体颜色插件 Ba-AppBar
    【Linux】select多路转接
    【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第一篇 嵌入式Linux入门篇-第六章 Vim 编辑器的使用
    DES加密前端入参
  • 原文地址:https://www.cnblogs.com/toutou/p/17063030.html