数据脱敏 用*替代实现

数据脱敏技术详解

一 什么是数据脱敏

数据脱敏(Data Masking),顾名思义,是屏蔽敏感数据,对某些敏感信息(比如,身份证号、手机号、卡号、客户姓名、客户地址、邮箱地址、薪资等等 )通过脱敏规则进行数据的变形,实现隐私数据的可靠保护。业界常见的脱敏规则有,替换、重排、加密、截断、掩码,用户也可以根据期望的脱敏算法自定义脱敏规则。

二 姓名脱敏小案例

  • 2.1 定长脱敏

所谓定长脱敏,就是替换的’*'的长度固定,效果如下图所示

SELECT
	CONCAT( LEFT ( real_name, 1 ), '*', RIGHT ( real_name, CHAR_LENGTH( real_name )- 2 ) ) AS username 
FROM
	sys_user;

<?php
/**
 * Notes:信息脱敏函数
 *
 * @param        $string 字符串
 * @param int    $start  开始明文长度
 * @param int    $end    结束明文长度
 * @param string $re     替换字符
 * @return string
 */
function desensitize($string, $start = 0, $end = 0, $re = '*')
{
    if (empty($string) || empty($end) || empty($re)) {
        return $string;
    }

    $strLen = strlen($string);
    if ($strLen < ($start + $end)) {
        return $string;
    }

    $strEnd = $strLen - $end;
    for ($i = 0; $i < $strLen; $i++) {
        if ($i >= $start && $i < $strEnd) {
            $str_arr[] = $re;
        } else {
            $str_arr[] = mb_substr($string, $i, 1);
        }
    }

    return implode('', $str_arr);
}
$name = '王刚';
$mobile = '13817558198';

$name = desensitize($name, 1, 1);
$mobile = desensitize($mobile, 3, 4);

var_dump($name);
var_dump($mobile);
  • 2.2 非定长脱敏

所谓非定长脱敏,就是替换的’*'长度不定,要根据姓名实时变化;

方式一

SELECT
 rpad(
  substring(u.real_name, 1, 1),
  char_length(u.real_name),
  '*'
 )
FROM
 sys_user u;

方式二

SELECT
  CONCAT( LEFT ( real_name, 1 ),  repeat('*',CHAR_LENGTH( real_name )- 1)) AS username 
FROM
  sys_user;

 

Java手机号码脱敏

public class PhoneMasking {

    public static String maskPhoneNumber(String phoneNumber) {
        if (phoneNumber == null || phoneNumber.length() <8) {
            throw new IllegalArgumentException("号码长度不够,不支持脱敏");
        }

        // 截取前三位和后四位
        String prefix = phoneNumber.substring(0, 3);
        String suffix = phoneNumber.substring(phoneNumber.length() - 4);

        // 中间部分用星号替代
        StringBuilder maskedPart = new StringBuilder();
        for (int i = 0; i < phoneNumber.length() - 7; i++) {
            maskedPart.append("*");
        }

        // 拼接脱敏后的手机号码
        return prefix + maskedPart.toString() + suffix;
    }

    public static void main(String[] args) {
        String phoneNumber = "13812345678";
        String maskedNumber = maskPhoneNumber(phoneNumber);
        System.out.println("Masked phone number: " + maskedNumber);
    }
}

姓名脱敏

package com.hworld.custom.common.util;

/**
 * 姓名脱敏工具类
 *
 * @author hudy
 */
public class NameDesensitizer {

  /**
   * 姓名脱敏,只保留姓氏,格式为 姓**
   *
   * @param name 原始姓名
   * @return 脱敏后的姓名,格式为 姓**
   */
  public static String desensitize(String name) {
    // 处理空值情况
    if (name == null || name.isEmpty()) {
      return name;
    }

    // 处理只有一个字符的情况
    if (name.length() == 1) {
      return name;
    }

    // 保留第一个字符(姓氏),其余用**替代
    return name.charAt(0) + "**";
  }

  /**
   * 姓名脱敏,保留姓氏并根据原名长度调整星号数量
   *
   * @param name 原始姓名
   * @return 脱敏后的姓名
   */
  public static String desensitizeWithLength(String name) {
    // 处理空值情况
    if (name == null || name.isEmpty()) {
      return name;
    }

    // 处理只有一个字符的情况
    if (name.length() == 1) {
      return name;
    }

    // 保留第一个字符(姓氏),其余用*替代
    StringBuilder result = new StringBuilder();
    result.append(name.charAt(0));

    // 根据原名长度添加相应数量的星号(减去姓氏的1个字符)
    for (int i = 1; i < name.length(); i++) {
      result.append("*");
    }

    return result.toString();
  }

  /**
   * 更安全的姓名脱敏方法,处理特殊字符和Unicode
   *
   * @param name 原始姓名
   * @return 脱敏后的姓名
   */
  public static String desensitizeSafe(String name) {
    // 处理空值情况
    if (name == null || name.isEmpty()) {
      return name;
    }

    // 使用code point处理Unicode字符
    int codePointCount = name.codePointCount(0, name.length());

    // 处理只有一个字符的情况
    if (codePointCount == 1) {
      return name;
    }

    // 获取第一个字符(姓氏)
    int firstCharEndIndex = name.offsetByCodePoints(0, 1);
    String firstName = name.substring(0, firstCharEndIndex);

    // 返回姓氏加**
    return firstName + "**";
  }
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值