本文目录导读:

在 PHP 中进行数据静态脱敏,主要有以下几种常用方法,我会从简单到复杂依次介绍:
基础字符串函数脱敏(最简单)
使用 substr_replace、str_repeat 等函数实现基本脱敏:
<?php
// 手机号脱敏:保留前3后4
function maskMobile($mobile) {
return substr_replace($mobile, '****', 3, 4);
}
// 身份证号脱敏:保留前6后4
function maskIdCard($idCard) {
return substr_replace($idCard, '********', 6, 8);
}
// 邮箱脱敏
function maskEmail($email) {
$parts = explode('@', $email);
$name = $parts[0];
$maskedName = substr($name, 0, 2) . str_repeat('*', strlen($name) - 2);
return $maskedName . '@' . $parts[1];
}
// 测试
echo maskMobile('13812345678'); // 138****5678
echo "\n";
echo maskIdCard('110101199001011234'); // 110101********1234
echo "\n";
echo maskEmail('zhangsan@example.com'); // zh*****@example.com
使用正则表达式脱敏
适合更复杂的脱敏规则:
<?php
function maskWithRegex($data, $type) {
switch ($type) {
case 'bank_card': // 银行卡号
return preg_replace('/(\d{4})\d{8}(\d{4})/', '$1********$2', $data);
case 'name': // 姓名:保留姓
return preg_replace('/([\x{4e00}-\x{9fa5}])./u', '$1*', $data);
case 'address': // 地址:保留前6个字符
return mb_substr($data, 0, 6) . str_repeat('*', mb_strlen($data) - 6);
}
return $data;
}
echo maskWithRegex('6222020200012345678', 'bank_card'); // 6222********4567
echo "\n";
echo maskWithRegex('张三', 'name'); // 张*
echo "\n";
echo maskWithRegex('北京市朝阳区某某街道', 'address'); // 北京市朝阳*****
数组批量脱敏
当需要处理多条记录时:
<?php
class DataMasker {
// 脱敏规则映射
private static $rules = [
'mobile' => ['type' => 'fixed', 'start' => 3, 'length' => 4],
'id_card' => ['type' => 'fixed', 'start' => 6, 'length' => 8],
'real_name' => ['type' => 'name'],
'email' => ['type' => 'email'],
'bank_card' => ['type' => 'regex', 'pattern' => '/(\d{4})\d{8}(\d{4})/', 'replacement' => '$1********$2'],
];
// 批量脱敏
public static function maskArray(array $data, array $fields) {
foreach ($data as &$row) {
foreach ($fields as $field => $ruleName) {
if (isset($row[$field])) {
$row[$field] = self::mask($row[$field], $ruleName);
}
}
}
return $data;
}
// 单个字段脱敏
public static function mask($value, $ruleName) {
if (empty($value)) return $value;
$rule = self::$rules[$ruleName] ?? null;
if (!$rule) return $value;
switch ($ruleName) {
case 'mobile':
case 'id_card':
return substr_replace(
$value,
str_repeat('*', $rule['length']),
$rule['start'],
$rule['length']
);
case 'real_name':
return mb_substr($value, 0, 1) . str_repeat('*', mb_strlen($value) - 1);
case 'email':
$parts = explode('@', $value);
return substr($parts[0], 0, 2) . '***@' . $parts[1];
case 'bank_card':
return preg_replace($rule['pattern'], $rule['replacement'], $value);
}
return $value;
}
}
// 使用示例
$users = [
[
'id' => 1,
'name' => '张三',
'mobile' => '13812345678',
'email' => 'zhangsan@example.com',
'id_card' => '110101199001011234'
],
[
'id' => 2,
'name' => '李四',
'mobile' => '13987654321',
'email' => 'lisi@example.com',
'id_card' => '110101199202022345'
]
];
$masked = DataMasker::maskArray($users, [
'name' => 'real_name',
'mobile' => 'mobile',
'email' => 'email',
'id_card' => 'id_card'
]);
print_r($masked);
结合数据库查询的脱敏
处理从数据库查询出来的数据:
<?php
class UserService {
private $db;
public function __construct(PDO $db) {
$this->db = $db;
}
// 获取用户列表(已脱敏)
public function getUsersWithMask(): array {
$stmt = $this->db->query("SELECT id, name, mobile, email FROM users");
$users = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 应用脱敏规则
foreach ($users as &$user) {
$user['name'] = $this->maskName($user['name']);
$user['mobile'] = $this->maskMobile($user['mobile']);
$user['email'] = $this->maskEmail($user['email']);
}
return $users;
}
// 获取敏感数据(不脱敏,内部使用)
public function getRawUser($id): ?array {
$stmt = $this->db->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$id]);
return $stmt->fetch(PDO::FETCH_ASSOC);
}
}
使用第三方库(推荐)
可以使用 fakerphp/faker 或自定义的脱敏类库:
composer require fakerphp/faker
<?php
require_once 'vendor/autoload.php';
use Faker\Factory;
class DataDesensitizer {
private $faker;
public function __construct() {
$this->faker = Factory::create('zh_CN');
}
// 生成脱敏数据
public function generateMaskedData() {
return [
'name' => $this->maskName(),
'mobile' => $this->maskMobile(),
'id_card' => $this->maskIdCard(),
];
}
private function maskName() {
// 生成近似人名
$lastNames = ['张', '李', '王', '刘', '陈'];
return $lastNames[array_rand($lastNames)] . '某';
}
private function maskMobile() {
return '138****' . $this->faker->numerify('####');
}
private function maskIdCard() {
return $this->faker->numerify('########') . '********' . $this->faker->numerify('####');
}
}
完整的脱敏工具类
<?php
class SensitiveDataMasker {
// 支持的脱敏类型
const MASK_FIXED = 'fixed'; // 固定位置脱敏
const MASK_REGEX = 'regex'; // 正则脱敏
const MASK_NAME = 'name'; // 姓名脱敏
const MASK_EMAIL = 'email'; // 邮箱脱敏
const MASK_ADDRESS = 'address'; // 地址脱敏
// 通用脱敏方法
public static function mask($value, $type, $options = []) {
switch ($type) {
case self::MASK_FIXED:
return self::maskFixed($value, $options['start'] ?? 3,
$options['length'] ?? 4,
$options['char'] ?? '*');
case self::MASK_REGEX:
return self::maskRegex($value, $options['pattern'],
$options['replacement']);
case self::MASK_NAME:
return self::maskName($value);
case self::MASK_EMAIL:
return self::maskEmail($value);
case self::MASK_ADDRESS:
$keep = $options['keep'] ?? 6;
return self::maskAddress($value, $keep);
default:
return $value;
}
}
private static function maskFixed($value, $start, $length, $char) {
return substr_replace($value, str_repeat($char, $length), $start, $length);
}
private static function maskRegex($value, $pattern, $replacement) {
return preg_replace($pattern, $replacement, $value);
}
private static function maskName($value) {
return mb_substr($value, 0, 1) . str_repeat('*', mb_strlen($value) - 1);
}
private static function maskEmail($value) {
$parts = explode('@', $value);
$len = strlen($parts[0]);
$keep = max(2, $len - 3);
return substr($parts[0], 0, $keep) . str_repeat('*', $len - $keep) . '@' . $parts[1];
}
private static function maskAddress($value, $keep) {
return mb_substr($value, 0, $keep) . str_repeat('*', mb_strlen($value) - $keep);
}
}
// 使用示例
echo SensitiveDataMasker::mask('13812345678', 'fixed', ['start' => 3, 'length' => 4]);
// 138****5678
总结建议
- 生产环境:建议使用专门的脱敏类库或框架
- 性能考虑:大批量数据时使用 SQL 层脱敏(如
CONCAT、SUBSTRING) - 安全性:脱敏不能完全替代权限控制
- 测试环境:可以使用
faker生成真实度高的测试数据
选择哪种方式取决于你的具体需求、数据量和性能要求。
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播