PHP 怎么PHP 数据屏蔽

wen PHP项目 3

本文目录导读:

PHP 怎么PHP 数据屏蔽

  1. 什么是数据屏蔽
  2. 基本实现方法
  3. 灵活可配置的屏蔽函数
  4. 批量数据屏蔽
  5. 数据库查询时屏蔽
  6. JSON输出时自动屏蔽
  7. 注意事项
  8. 最佳实践建议

我来帮你详细解释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"}
?>

注意事项

  1. 性能考虑:大量数据处理时使用字符串函数比正则表达式快
  2. 编码问题:中文等Unicode字符使用mb_*函数
  3. 安全性:确保屏蔽后的数据不能还原
  4. 一致性:在不同接口中保持相同的屏蔽规则

最佳实践建议

<?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
?>

这样你就可以根据实际需求选择合适的屏蔽方式了。

抱歉,评论功能暂时关闭!