本文目录导读:

我来帮你详细解释PHP中的数据屏蔽(Data Masking)的多种实现方法。
什么是数据屏蔽
数据屏蔽是对敏感信息进行部分隐藏的处理方式,常见于:
- 手机号:138****1234
- 身份证:110*1234
- 银行卡号:62221234
基本实现方法
1 简单字符串替换
<?php
// 手机号屏蔽
function maskPhone($phone) {
return substr($phone, 0, 3) . '****' . substr($phone, -4);
}
// 邮箱屏蔽
function maskEmail($email) {
$parts = explode('@', $email);
$name = substr($parts[0], 0, 2) . '***';
return $name . '@' . $parts[1];
}
// 身份证屏蔽
function maskIdCard($id) {
return substr($id, 0, 6) . '********' . substr($id, -4);
}
// 测试
echo maskPhone('13812345678'); // 138****5678
echo maskEmail('example@test.com'); // ex***@test.com
echo maskIdCard('110101199001011234'); // 110101****1234
?>
2 使用正则表达式
<?php
// 银行卡号屏蔽
function maskBankCard($card) {
return preg_replace('/(\d{4})\d{8}(\d{4})/', '$1********$2', $card);
}
// 姓名屏蔽(保留姓氏)
function maskName($name) {
return mb_substr($name, 0, 1) . str_repeat('*', mb_strlen($name) - 1);
}
// 测试
echo maskBankCard('6222021234567890'); // 6222********7890
echo maskName('张三'); // 张*
echo maskName('李小明'); // 李**
?>
灵活可配置的屏蔽函数
<?php
class DataMasker {
/**
* 通用数据屏蔽函数
* @param string $data 原始数据
* @param int $start 保留开头的字符数
* @param int $end 保留结尾的字符数
* @param string $mask 屏蔽字符
* @return string
*/
public static function mask($data, $start = 0, $end = 0, $mask = '*') {
$length = strlen($data);
if ($start + $end >= $length) {
return str_repeat($mask, $length);
}
$masked = substr($data, 0, $start);
$masked .= str_repeat($mask, $length - $start - $end);
$masked .= substr($data, -$end);
return $masked;
}
// 预定义的屏蔽规则
public static function phone($phone) {
return self::mask($phone, 3, 4);
}
public static function email($email) {
$parts = explode('@', $email);
$name = self::mask($parts[0], 1, 0);
return $name . '@' . $parts[1];
}
public static function idCard($id) {
return self::mask($id, 6, 4);
}
public static function bankCard($card) {
return self::mask($card, 4, 4);
}
}
?>
批量数据屏蔽
<?php
// 多维数组数据屏蔽
function maskArrayData($data) {
$rules = [
'phone' => 'maskPhone',
'email' => 'maskEmail',
'id_card' => 'maskIdCard',
'name' => 'maskName',
'bank_card' => 'maskBankCard'
];
foreach ($data as $key => &$value) {
if (is_array($value)) {
$value = maskArrayData($value);
} elseif (isset($rules[$key])) {
$value = $rules[$key]($value);
}
}
return $data;
}
// 使用示例
$userData = [
'name' => '张三',
'phone' => '13812345678',
'email' => 'zhangsan@test.com',
'id_card' => '110101199001011234',
'bank_card' => '6222021234567890'
];
$maskedData = maskArrayData($userData);
print_r($maskedData);
?>
数据库查询时屏蔽
<?php
// MySQL查询时屏蔽手机号
$sql = "SELECT
CONCAT(LEFT(phone, 3), '****', RIGHT(phone, 4)) as masked_phone,
CONCAT(LEFT(email, 2), '***', '@', SUBSTRING_INDEX(email, '@', -1)) as masked_email
FROM users";
// 或者使用自定义函数
$sql = "SELECT
mask_phone(phone) as masked_phone,
mask_email(email) as masked_email
FROM users";
?>
JSON输出时自动屏蔽
<?php
class MaskedJson {
private $data;
private $maskRules;
public function __construct($data) {
$this->data = $data;
$this->maskRules = [
'phone' => [$this, 'maskPhone'],
'email' => [$this, 'maskEmail'],
// 添加更多规则
];
}
public function toJson() {
$this->applyMasking($this->data);
return json_encode($this->data, JSON_UNESCAPED_UNICODE);
}
private function applyMasking(&$data) {
foreach ($data as $key => &$value) {
if (is_array($value)) {
$this->applyMasking($value);
} elseif (isset($this->maskRules[$key])) {
$value = call_user_func($this->maskRules[$key], $value);
}
}
}
private function maskPhone($phone) {
return substr($phone, 0, 3) . '****' . substr($phone, -4);
}
private function maskEmail($email) {
$parts = explode('@', $email);
return substr($parts[0], 0, 2) . '***@' . $parts[1];
}
}
// 使用
$data = ['name' => '张三', 'phone' => '13812345678'];
$masked = new MaskedJson($data);
echo $masked->toJson(); // {"name":"张三","phone":"138****5678"}
?>
注意事项
- 性能考虑:大量数据处理时使用字符串函数比正则表达式快
- 编码问题:中文等Unicode字符使用
mb_*函数 - 安全性:确保屏蔽后的数据不能还原
- 一致性:在不同接口中保持相同的屏蔽规则
最佳实践建议
<?php
// 定义统一的屏蔽服务
class MaskService {
public static function mask($type, $data) {
switch ($type) {
case 'phone':
return preg_replace('/(\d{3})\d{4}(\d{4})/', '$1****$2', $data);
case 'email':
return preg_replace('/(.{2}).*(@.*)/', '$1***$2', $data);
case 'name':
return mb_substr($data, 0, 1) . str_repeat('*', mb_strlen($data) - 1);
default:
return $data;
}
}
}
// 使用
echo MaskService::mask('phone', '13812345678'); // 138****5678
?>
这样你就可以根据实际需求选择合适的屏蔽方式了。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播