一 什么是数据脱敏
数据脱敏(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 + "**";
}
}
数据脱敏技术详解
730

被折叠的 条评论
为什么被折叠?



