本文目录导读:

在PHP项目中记录异常信息时,对敏感数据进行脱敏处理是保护用户隐私和安全的重要措施,以下是几种常见的脱敏方案和实现方法:
基础脱敏方案
手机号脱敏
function maskPhone($phone) {
if (empty($phone)) return '';
return substr($phone, 0, 3) . '****' . substr($phone, -4);
}
// 188****8888
邮箱脱敏
function maskEmail($email) {
if (empty($email)) return '';
$parts = explode('@', $email);
$name = $parts[0];
$domain = $parts[1] ?? '';
$maskedName = substr($name, 0, 2) . str_repeat('*', strlen($name) - 2);
return $maskedName . '@' . $domain;
}
// ab***@example.com
身份证号脱敏
function maskIdCard($idCard) {
if (empty($idCard)) return '';
return substr($idCard, 0, 6) . '********' . substr($idCard, -4);
}
// 110101********1234
通用脱敏类
class DataMasker {
private static $patterns = [
'phone' => [
'pattern' => '/(1[3-9]\d)\d{4}(\d{4})/',
'replacement' => '$1****$2'
],
'email' => [
'pattern' => '/(\w{2})\w*@(\w+\.\w+)/',
'replacement' => '$1***@$2'
],
'id_card' => [
'pattern' => '/^(\d{6})\d{8}(\d{4})$/',
'replacement' => '$1********$2'
],
'bank_card' => [
'pattern' => '/^(\d{4})\d{8,12}(\d{4})$/',
'replacement' => '$1****$2'
],
'password' => [
'pattern' => '/password["\']?\s*[:=]\s*["\'].*?["\']/i',
'replacement' => 'password"***"'
],
'token' => [
'pattern' => '/token["\']?\s*[:=]\s*["\'].*?["\']/i',
'replacement' => 'token"***"'
]
];
public static function mask($data, $type = null) {
if ($type && isset(self::$patterns[$type])) {
return preg_replace(
self::$patterns[$type]['pattern'],
self::$patterns[$type]['replacement'],
$data
);
}
// 自动检测并脱敏
$result = $data;
foreach (self::$patterns as $type => $rule) {
$result = preg_replace($rule['pattern'], $rule['replacement'], $result);
}
return $result;
}
public static function maskArray($data, $fields = []) {
if (empty($fields)) {
$fields = ['phone', 'email', 'id_card', 'bank_card', 'password', 'token'];
}
foreach ($data as $key => &$value) {
if (in_array($key, $fields)) {
if (method_exists(self, 'mask' . ucfirst($key))) {
$value = self::{'mask' . ucfirst($key)}($value);
}
} elseif (is_array($value)) {
$value = self::maskArray($value, $fields);
}
}
return $data;
}
}
集成到日志系统
Monolog 处理器
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Processor\ProcessorInterface;
class SensitiveDataProcessor implements ProcessorInterface {
private $fields = ['password', 'token', 'credit_card', 'ssn'];
private $masker;
public function __construct() {
$this->masker = new DataMasker();
}
public function __invoke(array $record): array {
// 处理上下文中的敏感数据
if (isset($record['context'])) {
$record['context'] = DataMasker::maskArray($record['context'], $this->fields);
}
// 处理异常信息
if (isset($record['context']['exception'])) {
$record['context']['exception'] = $this->maskException($record['context']['exception']);
}
// 处理消息本身
$record['message'] = DataMasker::mask($record['message']);
return $record;
}
private function maskException($exception) {
if ($exception instanceof \Throwable) {
return [
'class' => get_class($exception),
'message' => DataMasker::mask($exception->getMessage()),
'file' => $exception->getFile(),
'line' => $exception->getLine(),
'trace' => $this->maskTrace($exception->getTraceAsString())
];
}
return $exception;
}
private function maskTrace($trace) {
// 脱敏栈追踪中的敏感信息
return DataMasker::mask($trace);
}
}
// 使用示例
$logger = new Logger('app');
$logger->pushProcessor(new SensitiveDataProcessor());
$logger->pushHandler(new StreamHandler('/var/log/app.log', Logger::DEBUG));
自定义日志包装器
class SafeLogger {
private $logger;
private $sensitiveKeys = ['password', 'token', 'secret', 'authorization'];
public function __construct($logger) {
$this->logger = $logger;
}
public function error($message, array $context = []) {
$safeMessage = $this->maskSensitiveData($message);
$safeContext = $this->maskContext($context);
$this->logger->error($safeMessage, $safeContext);
}
public function exception(\Throwable $e, array $context = []) {
$safeContext = $this->maskContext($context);
$safeMessage = DataMasker::mask($e->getMessage());
$this->logger->error($safeMessage, array_merge([
'exception' => [
'class' => get_class($e),
'message' => $safeMessage,
'code' => $e->getCode(),
'file' => $this->maskFilePath($e->getFile()),
'line' => $e->getLine()
]
], $safeContext));
}
private function maskSensitiveData($data) {
if (is_string($data)) {
return DataMasker::mask($data);
}
return $data;
}
private function maskContext(array $context) {
foreach ($context as $key => $value) {
if (in_array(strtolower($key), $this->sensitiveKeys)) {
$context[$key] = '***MASKED***';
} elseif (is_array($value)) {
$context[$key] = $this->maskContext($value);
}
}
return $context;
}
private function maskFilePath($file) {
// 脱敏用户目录路径
$homePath = getenv('HOME') ?: '/home';
return str_replace($homePath, '/home/***', $file);
}
}
框架集成示例
Laravel 集成
// app/Exceptions/Handler.php
namespace App\Exceptions;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use App\Logging\SensitiveDataProcessor;
class Handler extends ExceptionHandler
{
protected function context()
{
try {
$context = parent::context();
// 脱敏敏感数据
$processor = new SensitiveDataProcessor();
return $processor->__invoke(['context' => $context])['context'];
} catch (\Throwable $e) {
return [];
}
}
}
ThinkPHP 集成
// app/provider.php
return [
'think\Log' => [
'type' => 'File',
'path' => './runtime/log/',
'processor' => \app\common\SensitiveDataProcessor::class,
],
];
自定义脱敏规则
class SensitiveDataFilter {
private $rules = [];
public function addRule($pattern, $replacement) {
$this->rules[] = [
'pattern' => $pattern,
'replacement' => $replacement
];
}
public function filter($data) {
if (is_array($data)) {
return array_map([$this, 'filter'], $data);
}
$result = $data;
foreach ($this->rules as $rule) {
$result = preg_replace($rule['pattern'], $rule['replacement'], $result);
}
return $result;
}
}
// 使用示例
$filter = new SensitiveDataFilter();
$filter->addRule('/\b\d{16,19}\b/', '****-****-****-****'); // 信用卡号
$filter->addRule('/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/', '***@***.***'); // 邮箱
最佳实践建议
配置管理
class SensitiveConfig {
private static $instance;
private $config;
private function __construct() {
$this->config = require __DIR__ . '/sensitive_config.php';
}
public static function getInstance() {
if (!self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
public function getMaskRules() {
return $this->config['mask_rules'] ?? [];
}
public function getSensitiveFields() {
return $this->config['sensitive_fields'] ?? [];
}
}
// sensitive_config.php
return [
'mask_rules' => [
'phone' => '/(1[3-9]\d)\d{4}(\d{4})/',
'email' => '/(\w{2})\w*@(\w+\.\w+)/',
],
'sensitive_fields' => [
'password', 'token', 'secret', 'credit_card', 'ssn'
]
];
日志记录注意事项
- 分级记录:不同级别的日志记录不同详细程度的信息
- 定期审计:定期检查日志中是否包含未脱敏的敏感信息
- 开发环境:开发环境可以记录更多信息,但生产环境必须严格脱敏
- 错误码系统:使用错误码代替具体的错误信息
通过合理实现上述方案,可以有效保护用户隐私和系统安全,同时保证异常信息的可追溯性。
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播