Java 安全的打印对象数据到日志

  • 在开发中有时候需要打印一些对象的属性值, 但是其中含有一些敏感字段, 不能打印明文而是需要脱敏打印,写了一个工具, 可以将对象转换成JSON字符串,并且可以指定要脱敏的字段名称
java 复制代码
package com.visy.utils;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;

import java.util.Arrays;

public class LogUtil {
   /**
    * 安全的JSON字符串转换(可脱敏)
    * @param obj 待序列化对象
    * @param fieldNames 待脱敏的字段名称
    * @return JSON字符串
    */
   public static String toJsonSafety(Object obj, String... fieldNames){
      if(fieldNames==null || fieldNames.length==0){
         return toJson(obj);
      }
      JSONObject jsonObject = (JSONObject) JSON.toJSON( obj);
      for(String fieldName : fieldNames){
         Object value = jsonObject.get(fieldName);
         if(ObjectUtil.isNotNull(value)){
            jsonObject.put(fieldName, mask(value.toString()));
         }
      }
      return toJson(jsonObject);
   }

   private static String toJson(Object obj){
      return JSON.toJSONString(obj, SerializerFeature.WriteMapNullValue);
   }

   /**
    * 字符串脱敏方法(自动计算并隐藏部分字符)
    * @param value 待脱敏的字符串
    * @return 脱敏后的字符串
    */
   public static String mask(String value){
      if(value == null || value.isEmpty()){
         return value;
      }
      int length = value.length(), halfLength = length / 2;
      if(halfLength <= 1){ // 1 ~ 3 个字符, 全部脱敏
         return createRepeatedString('*', length);
      }else{ // >= 4 个字符, 前后各保留1/4 个字符
         int beforeLength = halfLength / 2;
         return mask(value, '*', beforeLength, halfLength-beforeLength);
      }
   }

   /**
    * 数据脱敏方法
    * @param value 待脱敏的原始数据
    * @param ch 脱敏占位字符
    * @param beforeLength 前保留字符数
    * @param afterLength 后保留字符数
    * @return 脱敏后的数据
    */
   public static String mask(String value, char ch, int beforeLength, int afterLength) {
      // 空值安全检查
      if (value == null || value.isEmpty()) {
         return value;
      }
      final int length = value.length(), leastLength = beforeLength + afterLength;

      // 长度小于等于leastLength位,全部脱敏
      if (length <= leastLength) {
         if(length <= afterLength){
            // 剩余长度小于等于afterLength,全部脱敏
            return createRepeatedString(ch, length);
         }
         // 剩余长度大于afterLength,只脱敏前length-afterLength位
         return createRepeatedString(ch, length-afterLength) + value.substring(length-afterLength);
      }
      return value.substring(0, beforeLength) + createRepeatedString(ch, length-leastLength) + value.substring(length-afterLength);
   }

   /**
    * 创建重复字符的字符串
    * @param ch 要重复的字符
    * @param count 重复次数
    * @return 重复字符组成的字符串
    */
   private static String createRepeatedString(char ch, int count) {
      if (count <= 0) {
         return "";
      }
      char[] chars = new char[count];
      Arrays.fill(chars, ch);
      return new String(chars);
   }
}
  • 使用
java 复制代码
public class LogUtilTest {
	public static void main(String[] args) {
      User user = new User();
      user.setName("张三");
      user.setAge(22);
      user.setIdCard("320381198812252138");

      //打印结果:{"idCard":"3203*********52138","name":"张三","age":22}
      System.out.println(LogUtil.toJsonSafety(user, "idCard"));
   }

   @Data
   static class User{
      private String name;
      private Integer age;
      private String idCard;
   }
}
相关推荐
linweidong2 小时前
中科闻歌Java面试题及参考答案
java·python·大模型·提示词·ai agent·mcp·rag原理
OpenAnolis小助手2 小时前
一句话看透 JVM,SysOM 诊断 Skill 新增 Java 应用诊断能力
java·开发语言·jvm·阿里云·操作系统控制台·sysom
ForteScarlet3 小时前
Kotlin 2.4.20 现已发布,新特性多不多?
android·java·开发语言·开源·kotlin·jetbrains
萧瑟余晖3 小时前
Java深入解析篇六十二之安全机制详解
java·开发语言
小刘在重生~3 小时前
Java 常用类|包装类 装箱拆箱、Integer 缓存面试题
java·python·缓存
Orange_sparkle3 小时前
Pi Agent vs LangGraph:从人机交互、企业 RAG 到持久化工作流的完整选型指南
java·网络·人机交互
Flynt4 小时前
"只输出 JSON"根本不够:LLM 结构化输出的坑,我实测了 60 次调用
llm·json
Wang's Blog5 小时前
Java框架快速入门: Spring Security+OAuth2之过滤器与过滤器链
java·开发语言·spring
谢尔登5 小时前
01_Java基础速通
java·开发语言
lemon_sjdk6 小时前
javafx-Image图像(2)
java·javafx