java 日志的数据脱敏的实现方法

数据脱敏是指对某些敏感信息通过脱敏规则进行数据的变形,实现敏感隐私数据的可靠保护。在涉及客户安全数据或者一些商业性敏感数据的情况下,在不违反系统规则条件下,对真实数据进行改造并提供测试使用,如身份证号、手机号、卡号、客户号等个人信息都需要进行数据脱敏,数据库安全技术之一。

比如我们现在有个user表,含有名字,性别,邮箱,电话号码等字段,但是当查看这些数据时,我们又不希望这些数据被暴露,这时可以对这些数据进行脱敏处理,当然可以根据需要选择哪些字段需要脱敏,然后再输出,至于怎么选择的,是另外一回事了。

思路

1。在 model层进行处理,直接重写get方法,在写一个getPlain 获取明文方法。(缺点:数据库写入和json序列化传递时使用的都是密文)

2.利用 日志组件过滤 特定的key,去进行脱敏(缺点:对所有的日志输出全部要正则匹配,非常耗时。)

由1,2的利弊,肯定会选择1,然后考虑一种实现(在model层定义方法,获取它的一个复制类,复制类里面的信息都是脱敏的,日志输出时只输出 复制对象),克服掉1的缺点

1.定义接口类

public interface NoSensitiveObj<T> {

 default T noSensitiveObj(){
  return (T) this;
 }
}

2.实现类 如果这个类没有敏感信息,只实现 NoSensitiveObj ,不需要实现里面的方法

public class User implements NoSensitiveObj<User>{

 private String name;

 private String phone;

 private String email;

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public String getPhone() {
  return phone;
 }

 public void setPhone(String phone) {
  this.phone = phone;
 }

 public String getEmail() {
  return email;
 }

 public void setEmail(String email) {
  this.email = email;
 }

 @Override
 public User noSensitiveObj() {
   User t;
   t=new User();
   t.setEmail(SensitiveInfoUtils.email(email));
   t.setName(SensitiveInfoUtils.chineseName(name));
   t.setPhone(SensitiveInfoUtils.mobilePhone(phone));
  return t;
 }

}

3.工具类

public class SensitiveInfoUtils {

 /**
  * [中文姓名] 只显示第一个汉字,其他隐藏为2个星号<例子:李**>
  */
 public static String chineseName(final String fullName) {
  if (StringUtils.isBlank(fullName)) {
   return "";
  }
  final String name = StringUtils.left(fullName, 1);
  return StringUtils.rightPad(name, StringUtils.length(fullName), "*");
 }

 /**
  * [中文姓名] 只显示第一个汉字,其他隐藏为2个星号<例子:李**>
  */
 public static String chineseName(final String familyName, final String givenName) {
  if (StringUtils.isBlank(familyName) || StringUtils.isBlank(givenName)) {
   return "";
  }
  return chineseName(familyName + givenName);
 }

 /**
  * [身份证号] 显示最后四位,其他隐藏。共计18位或者15位。<例子:*************5762>
  */
 public static String idCardNum(final String id) {
  if (StringUtils.isBlank(id)) {
   return "";
  }

  return StringUtils.left(id, 3).concat(StringUtils
    .removeStart(StringUtils.leftPad(StringUtils.right(id, 3), StringUtils.length(id), "*"), "***"));
 }

 /**
  * [固定电话] 后四位,其他隐藏<例子:****1234>
  */
 public static String fixedPhone(final String num) {
  if (StringUtils.isBlank(num)) {
   return "";
  }
  return StringUtils.leftPad(StringUtils.right(num, 4), StringUtils.length(num), "*");
 }

 /**
  * [手机号码] 前三位,后四位,其他隐藏<例子:138******1234>
  */
 public static String mobilePhone(final String num) {
  if (StringUtils.isBlank(num)) {
   return "";
  }
  return StringUtils.left(num, 2).concat(StringUtils
    .removeStart(StringUtils.leftPad(StringUtils.right(num, 2), StringUtils.length(num), "*"), "***"));

 }

 /**
  * [地址] 只显示到地区,不显示详细地址;我们要对个人信息增强保护<例子:北京市海淀区****>
  *
  * @param sensitiveSize
  *   敏感信息长度
  */
 public static String address(final String address, final int sensitiveSize) {
  if (StringUtils.isBlank(address)) {
   return "";
  }
  final int length = StringUtils.length(address);
  return StringUtils.rightPad(StringUtils.left(address, length - sensitiveSize), length, "*");
 }

 /**
  * [电子邮箱] 邮箱前缀仅显示第一个字母,前缀其他隐藏,用星号代替,@及后面的地址显示<例子:g**@163.com>
  */
 public static String email(final String email) {
  if (StringUtils.isBlank(email)) {
   return "";
  }
  final int index = StringUtils.indexOf(email, "@");
  if (index <= 1) {
   return email;
  } else {
   return StringUtils.rightPad(StringUtils.left(email, 1), index, "*")
     .concat(StringUtils.mid(email, index, StringUtils.length(email)));
  }
 }

 /**
  * [银行卡号] 前六位,后四位,其他用星号隐藏每位1个星号<例子:6222600**********1234>
  */
 public static String bankCard(final String cardNum) {
  if (StringUtils.isBlank(cardNum)) {
   return "";
  }
  return StringUtils.left(cardNum, 6).concat(StringUtils.removeStart(
    StringUtils.leftPad(StringUtils.right(cardNum, 4), StringUtils.length(cardNum), "*"), "******"));
 }

 /**
  * [公司开户银行联号] 公司开户银行联行号,显示前两位,其他用星号隐藏,每位1个星号<例子:12********>
  */
 public static String cnapsCode(final String code) {
  if (StringUtils.isBlank(code)) {
   return "";
  }
  return StringUtils.rightPad(StringUtils.left(code, 2), StringUtils.length(code), "*");
 }

}

4.测试

public class Test {

 private static final Logger logger=LoggerFactory.getLogger(Test.class);

 public static void main(String[] args) {
  User user=new User();
  user.setName("张三");
  user.setPhone("18666218777");
  user.setEmail("zhangsan@qq.com");
  System.out.println(JSON.toJSONString(user.noSensitiveObj()));

 }
}

结果

{"email":"z*******@qq.com","name":"张*","phone":"18******77"}

经过和同事讨论后,发现其实不需要这么复杂,只要在model 的tostring 方法中脱敏即可。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 浅谈java日志格式化

    1.日志的重要性 不管我们使用何种语言开发,一旦程序发生异常,日志是一个很重要的数据.但是并不是意味着打印的日志越多越好,我们需要的是有用的日志. 曾经参与一个很重要的项目优化,他们的日志没有进行规范,开发.运维也没有把这个事情放在心上.等到压测的时候TPS和响应时间一直上不去.通过jstack分析发现,大部分的log数据在阻塞! 今天我们不讨论具体的日志规范,我从日志中心的角度来聊下LOG的规范 2.日志采集分析 -ELK 目前主流的ELK系统应该都是通过agent端(filebeat/flu

  • 简单学习Java API 设计实践

    前言 了解在设计 Java API 时应该运用的一些 API 设计实践.这些实践通常很有用,而且可确保 API 能在诸如 OSGi 和 Java Platform Module System (JPMS) 之类的模块化环境中得到正确使用.有些实践是规定性的,有些则是禁止性的.当然,其他良好的 API 设计实践也同样适用. OSGi 环境提供了一个模块化运行时,使用 Java 类加载器概念来强制实施类型可见性封装.每个模块都将有自己的类加载器,该加载器将连接到其他模块的类加载器,以共享导出的包并使

  • Java日志组件间关系详解

    一. 总览 本文章不对日志组件进行优劣评价,只是对关系进行对比.在日志中组件中存在这样的几种关系, 这几种关系理解清楚, 有助于我们对日志的引入和使用. 二. 日志门面 日志门面就是指直接引入我们程序中进行记录日志的日志组件,作为日志门面的这些组件会在程序中直接依赖, 上图中就列举的几种常见的日志门面的组件.像一些软件直接回默认使用一些组件, 比如Spring使用的就是commons-logging, activiti使用的日志门面就是slf4j, 其他的软件也都会选用自己认为好用的日志门面.

  • 详解Java日志正确使用姿势

    前言 关于日志,在大家的印象中都是比较简单的,只须引入了相关依赖包,剩下的事情就是在项目中"尽情"的打印我们需要的信息了.但是往往越简单的东西越容易让我们忽视,从而导致一些不该有的bug发生,作为一名严谨的程序员,怎么能让这种事情发生呢?所以下面我们就来了解一下关于日志的那些正确使用姿势. 正文 日志规范 命名 首先是日志文件的命名,尽量要做到见名知意,团队里面也必须使用统一的命名规范,不然"脏乱差"的日志文件会影响大家排查问题的效率.这里推荐以"proj

  • Java8中Lambda表达式使用和Stream API详解

    前言 Java8 的新特性:Lambda表达式.强大的 Stream API.全新时间日期 API.ConcurrentHashMap.MetaSpace.总得来说,Java8 的新特性使 Java 的运行速度更快.代码更少.便于并行.最大化减少空指针异常. 0x00. 前置数据 private List<People> peoples = null; @BeforeEach void before () { peoples = new ArrayList<>(); peoples

  • 深入学习JAVA GC日志的相关知识

    GC环境模拟 首先我们给出如下代码用来触发GC public static void main(String[] args) { // 每100毫秒创建100线程,每个线程创建一个1M的对象,即每100ms申请100M堆空间 Executors.newScheduledThreadPool(1).scheduleAtFixedRate(() -> { for (int i = 0; i < 100; i++) { new Thread(() -> { try { // 申请1M byte

  • Java日志API管理最佳实践详解

    概述 对于现在的应用程序来说,日志的重要性是不言而喻的.很难想象没有任何日志记录功能的应用程序运行在生产环境中.日志所能提供的功能是多种多样的,包括记录程序运行时产生的错误信息.状态信息.调试信息和执行时间信息等.在生产环境中,日志是查找问题来源的重要依据.应用程序运行时的产生的各种信息,都应该通过日志 API 来进行记录. 很多开发人员习惯于使用 System.out.println.System.err.println 以及异常对象的 printStrackTrace 方法来输出相关信息.这

  • 深入了解Java 脚本化api编程

    Java脚本化API为谁准备? 脚本语言的一些有用的特性是: 方便:大多数脚本语言都是动态类型的.您通常可以创建新的变量,而不声明变量类型,并且您可以重用变量来存储不同类型的对象.此外,脚本语言往往会自动执行许多类型的转换,例如, 必要时 将数字10转换为"10". 开发快速原型:您可以避免编辑编译运行周期,只使用"编辑运行"! 应用扩展/定制:你可以"具体化"的部分应用程序,例如一些配置脚本,业务逻辑/规则和财务应用中的数学表达式 . 为应用添

  • java 日志的数据脱敏的实现方法

    数据脱敏是指对某些敏感信息通过脱敏规则进行数据的变形,实现敏感隐私数据的可靠保护.在涉及客户安全数据或者一些商业性敏感数据的情况下,在不违反系统规则条件下,对真实数据进行改造并提供测试使用,如身份证号.手机号.卡号.客户号等个人信息都需要进行数据脱敏,数据库安全技术之一. 比如我们现在有个user表,含有名字,性别,邮箱,电话号码等字段,但是当查看这些数据时,我们又不希望这些数据被暴露,这时可以对这些数据进行脱敏处理,当然可以根据需要选择哪些字段需要脱敏,然后再输出,至于怎么选择的,是另外一回事

  • 浅析Java类和数据结构中常用的方法

    1.Object类里面常用的方法: protected Object clone()创建并返回此对象的一个副本. boolean equals(Object obj)指示其他某个对象是否与此对象"相等". protected void finalize()当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法. Class<?> getClass()返回此 Object 的运行时类. int hashCode()返回该对象的哈希码值. void notif

  • Java利用Jackson序列化实现数据脱敏

    几天前使用了Jackson对数据的自定义序列化.突发灵感,利用此方法来简单实现接口返回数据脱敏,故写此文记录. 核心思想是利用Jackson的StdSerializer,@JsonSerialize,以及自己实现的数据脱敏过程. 使用效果如下: 首先在需要进行脱敏的VO字段上面标注相关脱敏注解 调用接口即可看到脱敏效果 实现过程如下: 1. 定义脱敏的过程实现 /** * Created by EalenXie on 2021/9/24 15:52 * 顶级的脱敏器 */ public inte

  • Java 如何通过注解实现接口输出时数据脱敏

    目录 Java注解实现接口输出数据脱敏 先声明了一个注解 我们目前只支持对手机号 然后我们需要实现注解的拦截功能 我对默认声明和脱敏名称和手机号进行了测试 Java注解的字段脱敏处理 定义需要脱敏的字段规则 声明注解 测试 Java注解实现接口输出数据脱敏 在后台管理中,对于手机号,身份证,姓名这些数据不允许所有人都能看,这时候我们要对相对数据进行脱敏. 先声明了一个注解 通过对相关接口函数进行声明,以及配置需要脱敏的参数类型SecretTypeEnum,默认脱敏手机号 /** * 脱敏声明 *

  • 简单了解Java日志脱敏框架sensitive

    这篇文章主要介绍了简单了解Java日志脱敏框架sensitive,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 问题 为了保证用户的信息安全,敏感信息需要脱敏. 项目开发过程中,每次处理敏感信息的日志问题感觉很麻烦,大部分都是用工具类单独处理,不利于以后统一管理,很不优雅. 于是,就写了一个基于 java 注解的日志脱敏工具. github sensitive 项目介绍 日志脱敏是常见的安全需求.普通的基于工具类方法的方式,对代码的入侵性太强.

  • 解说mysql之binlog日志以及利用binlog日志恢复数据的方法

    众所周知,binlog日志对于mysql数据库来说是十分重要的.在数据丢失的紧急情况下,我们往往会想到用binlog日志功能进行数据恢复(定时全备份+binlog日志恢复增量数据部分),化险为夷! 废话不多说,下面是梳理的binlog日志操作解说: 一.初步了解binlog MySQL的二进制日志binlog可以说是MySQL最重要的日志,它记录了所有的DDL和DML语句(除了数据查询语句select),以事件形式记录,还包含语句所执行的消耗的时间,MySQL的二进制日志是事务安全型的. ---

  • 使用Java构造和解析Json数据的两种方法(详解二)

    JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,采用完全独立于语言的文本格式,是理想的数据交换格式.同时,JSON是 JavaScript 原生格式,这意味着在 JavaScript 中处理 JSON数据不须要任何特殊的 API 或工具包. 在www.json.org上公布了很多JAVA下的json构造和解析工具,其中org.json和json-lib比较简单,两者使用上差不多但还是有些区别.下面接着介绍用org.json构造和解析Json数据的方法

  • 使用Java构造和解析Json数据的两种方法(详解一)

    JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,采用完全独立于语言的文本格式,是理想的数据交换格式.同时,JSON是 JavaScript 原生格式,这意味着在 JavaScript 中处理 JSON数据不须要任何特殊的 API 或工具包. 在www.json.org上公布了很多JAVA下的json构造和解析工具,其中org.json和json-lib比较简单,两者使用上差不多但还是有些区别.下面首先介绍用json-lib构造和解析Json数据的方法

  • java 在file的尾部添加数据的两种方法总结

    java 在file的尾部添加数据的两种方法总结 问题描述:   在文件的末尾追加内容 方法1:利用RandomAccessFile类  1.将randomAccessFile模式设置为rw  2将randomAccessFile移动(seek)到文件末尾  3追加数据  4关闭流 方法2:利用FileWriter类  1.将FileWriter构造方法第二个参数置为true.表示在尾部追加  2追加数据  3.关闭流 实现代码: package cn.com; import java.io.F

  • java多线程编程之从线程返回数据的两种方法

    一.通过类变量和方法返回数据 使用这种方法返回数据需要在调用start方法后才能通过类变量或方法得到数据.让我们先来看看例程2-13会得到什么结果. 复制代码 代码如下: package mythread; public class MyThread extends Thread{    private String value1;    private String value2; public void run()    {        value1 = "通过成员变量返回数据"

随机推荐