本文目录导读:

- 使用字符串函数直接脱敏(最常用)
- 基于用户权限的动态选择性披露
- 使用模型层的访问器(Laravel 风格)
- 使用中间件进行全局过滤(API 场景)
- 数据库级别的视图(只读场景)
- 处理 JSON 数据中的选择性披露
- 最佳实践建议
在 PHP 中实现“选择性披露”通常意味着:只向特定用户(或特定权限等级)显示部分敏感数据,而对其他用户隐藏或脱敏这些数据。
常见的应用场景包括:
- 用户手机号:显示
138****1234 - 用户邮箱:显示
a***@example.com - 银行卡号:显示
尾号 1234 - 系统密码:显示
- 用户真实姓名:只显示姓氏,如
张*
以下是几种常见的实现方案,按复杂度从低到高排列:
使用字符串函数直接脱敏(最常用)
这是最直接、性能最好的方式,适用于固定格式的数据。
function maskPhone($phone) {
return substr($phone, 0, 3) . '****' . substr($phone, -4);
}
function maskEmail($email) {
$parts = explode('@', $email);
$name = $parts[0];
$domain = $parts[1];
// 隐藏用户名的一部分
$maskedName = substr($name, 0, 2) . str_repeat('*', max(0, strlen($name) - 4)) . substr($name, -1);
return $maskedName . '@' . $domain;
}
function maskName($name) {
if (mb_strlen($name) <= 1) {
return $name;
}
// 保留第一个字符,其余隐藏
return mb_substr($name, 0, 1) . str_repeat('*', mb_strlen($name) - 1);
}
// 使用示例
echo maskPhone('13812345678'); // 138****5678
echo maskEmail('example@test.com'); // ex****e@test.com
echo maskName('张三'); // 张*
基于用户权限的动态选择性披露
如果希望根据用户的角色(如普通用户、管理员、客服)来决定是否真正显示原数据:
class SelectiveDisclosure {
public static function maskSensitiveData($data, $type, $userRole = 'user') {
// 管理员/客服可以看到完整数据
if (in_array($userRole, ['admin', 'support'])) {
return $data;
}
switch ($type) {
case 'phone':
return substr($data, 0, 3) . '****' . substr($data, -4);
case 'email':
$parts = explode('@', $data);
$name = $parts[0];
$maskedName = substr($name, 0, 2) . '***';
return $maskedName . '@' . $parts[1];
case 'id_card':
return substr($data, 0, 3) . '********' . substr($data, -4);
default:
return '***';
}
}
}
// 使用
$userRole = getUserRole(); // 'admin' 或 'user'
echo SelectiveDisclosure::maskSensitiveData('13812345678', 'phone', $userRole);
使用模型层的访问器(Laravel 风格)
如果你使用 MVC 框架(如 Laravel),可以在模型层定义访问器,根据上下文自动处理。
// User.php
class User extends Model {
// 获取手机号时自动脱敏
public function getPhoneAttribute($value) {
// 检查当前用户是否允许查看原数据
if (auth()->user() && auth()->user()->can('view_sensitive_phone')) {
return $value;
}
return substr($value, 0, 3) . '****' . substr($value, -4);
}
// 获取邮箱时自动脱敏
public function getEmailAttribute($value) {
if (auth()->user() && auth()->user()->can('view_sensitive_email')) {
return $value;
}
$parts = explode('@', $value);
return substr($parts[0], 0, 2) . '***@' . $parts[1];
}
}
使用中间件进行全局过滤(API 场景)
对于 RESTful API,可以编写中间件在响应输出前替换敏感字段:
// SelectiveDisclosureMiddleware.php
class SelectiveDisclosureMiddleware {
public function handle($request, Closure $next) {
$response = $next($request);
// 只在响应中处理
if (method_exists($response, 'getData')) {
$data = $response->getData(true);
$data = $this->maskSensitiveFields($data, $request->user());
$response->setData($data);
}
return $response;
}
private function maskSensitiveFields($data, $user) {
// 深度遍历数组/对象,对特定字段进行脱敏
array_walk_recursive($data, function(&$value, $key) use ($user) {
if (in_array($key, ['phone', 'email', 'id_card'])) {
if (!$user || !$user->can('view_' . $key)) {
$value = maskField($key, $value);
}
}
});
return $data;
}
}
数据库级别的视图(只读场景)
如果希望直接在数据库层面做选择性披露,可以创建数据库视图:
-- 普通用户视图
CREATE VIEW user_safe_view AS
SELECT
id,
CONCAT(LEFT(phone, 3), '****', RIGHT(phone, 4)) as phone,
CONCAT(LEFT(email, 2), '***@', SUBSTRING_INDEX(email, '@', -1)) as email,
name
FROM users;
然后在 PHP 中根据用户角色决定查询哪个表或视图。
处理 JSON 数据中的选择性披露
如果数据以 JSON 存储(如 API 响应中的嵌套数组):
function maskJsonSensitiveData(array $data, string $userRole): array {
foreach ($data as $key => &$value) {
if ($key === 'phone' && is_string($value)) {
// 普通用户脱敏,管理员保留
$value = ($userRole === 'admin') ? $value : substr($value, 0, 3) . '****' . substr($value, -4);
} elseif (is_array($value)) {
$value = maskJsonSensitiveData($value, $userRole); // 递归处理嵌套
}
}
return $data;
}
最佳实践建议
| 场景 | 推荐方案 |
|---|---|
| 简单的字段脱敏(固定格式) | 字符串函数直接处理 |
| 需要根据用户权限动态披露 | 模型访问器 + 权限检查 |
| API 接口统一处理 | 中间件过滤 |
| 多语言/多字符集(中文字符) | 使用 mb_substr() 处理 |
| 性能敏感 | 在 SQL 查询中使用 CONCAT 直接脱敏 |
| 需要审计日志 | 在数据输出前记录原始值和脱敏后的值 |
安全提示:
- 永远不要在前端(JavaScript)做关键数据的选择性披露,因为前端代码可以被篡改。
- 所有敏感数据的脱敏操作必须在服务端(PHP)完成。
- 如果你需要“选择性地向不同用户展示不同数据”,建议配合一个权限系统来处理。
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播