导出用户数据时如何有效脱敏手机号和邮箱?
最近在做用户数据导出功能,需要脱敏手机号和邮箱,但实现后发现有些数据没处理好。
我写了这样的脱敏函数:
function anonymizeData(data) {
return data.map(user => ({
...user,
phone: user.phone.replace(/(d{3})d{4}(d{4})/, "$1****$2"),
email: user.email.replace(/^(.*?)(@.*)$/, "$1***$2")
}));
}
测试时发现手机号”13812345678″能变成”138****5678″没问题,但邮箱比如”test@example.com”被处理成”t***@example.com”,但当邮箱是”ab@example.com”时会变成”a***@example.com”,这样第一个字符泄露了?该怎么改才能保证中间至少保留4个星号?
关键是要把邮箱用户名部分强制截断处理,保留前1后1字符,中间用4个星号填充:
function anonymizeData(data) {
return data.map(user => ({
...user,
phone: user.phone.replace(/(d{3})d{4}(d{4})/, "$1$2"),
// 邮箱用户名部分保留前1后1,中间用4个星号连接
email: user.email.replace(/^([^@]{0,1})[^@]([^@]{0,1}@.)$/, "$1$2")
}));
}
这个正则表达式的意思:
^[^@]{0,1} 匹配开头最多1个非@字符
[^@] 匹配中间任意数量的非@字符(这部分会被替换)
([^@]{0,1}@.)$ 匹配结尾最多1个非@字符+@符号及后面完整域名
这样处理后:
test@example.com -> tt@example.com
ab@example.com -> ab@example.com
a1b2c3@example.com -> a3@example.com
手机号正则没问题,已经能保证中间4个星号。邮箱这里要特别注意用户名部分必须强制保留前1后1字符,中间统一用4个星号替代,才能避免你遇到的字符泄露问题。
你可以在脱敏前加一个判断,确保用户名部分足够长,再进行替换。否则可以整体替换为
****或者保留一个模糊版本。修改后的函数可以这样写:
这样处理:
- 如果邮箱用户名部分长度 >= 4,就统一替换成四个
*- 如果长度小于 4,比如是
ab,就替换成对应长度的*,避免泄露原始长度信息其实还可以再加一层判断,比如直接对邮箱用户名统一替换为固定长度的星号,例如永远显示
****@example.com,这样更安全,但具体取决于你的业务要求。建议:脱敏之前,对字段长度做校验,避免原始信息残留。脱敏的最终目标是防止敏感数据泄露,哪怕是一个字符都不应该暴露。