生产环境运行的系统会产生大量包含用户隐私、业务核心信息的文件,这些文件如果直接存储或传输,很容易引发数据泄露风险,因此用C#实现文件内容的敏感数据脱敏是很多开发场景的必备需求。常见的需要脱敏的敏感数据包括身份证号、手机号码、银行卡号、邮箱地址等,脱敏的核心思路是先识别文件中的敏感数据,再按照规则替换部分字符为掩码。

常见敏感数据的脱敏规则
不同敏感数据的脱敏规则存在差异,以下是生产环境中常用的脱敏标准:
- 身份证号:保留前6位和后4位,中间8位替换为星号
- 手机号:保留前3位和后4位,中间4位替换为星号
- 银行卡号:保留前6位和后4位,中间部分替换为星号
- 邮箱:保留邮箱前缀首字符和后缀域名,中间部分替换为星号
基于正则匹配的脱敏实现
正则表达式是识别敏感数据的高效方式,我们可以先定义不同敏感数据对应的正则模式,再编写通用的替换方法完成脱敏。以下是核心的正则匹配和替换逻辑代码:
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
public class DataDesensitizationHelper
{
// 手机号正则:1开头,11位数字
private static readonly Regex PhoneRegex = new Regex(@"1[3-9]d{9}");
// 身份证号正则:18位,最后一位可能是X
private static readonly Regex IdCardRegex = new Regex(@"d{17}[dXx]");
// 银行卡号正则:16-19位数字
private static readonly Regex BankCardRegex = new Regex(@"d{16,19}");
// 邮箱正则:包含@的合法邮箱格式
private static readonly Regex EmailRegex = new Regex(@"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}");
/// <summary>
/// 对输入文本进行全类型敏感数据脱敏
/// </summary>
/// <param name="content">待脱敏的文本</param>
/// <returns>脱敏后的文本</returns>
public static string DesensitizeContent(string content)
{
if (string.IsNullOrEmpty(content))
{
return content;
}
// 先处理身份证号,避免和银行卡号正则冲突
content = IdCardRegex.Replace(content, match =>
{
string value = match.Value;
return value.Substring(0, 6) + "********" + value.Substring(value.Length - 4);
});
// 处理手机号
content = PhoneRegex.Replace(content, match =>
{
string value = match.Value;
return value.Substring(0, 3) + "****" + value.Substring(7);
});
// 处理银行卡号
content = BankCardRegex.Replace(content, match =>
{
string value = match.Value;
return value.Substring(0, 6) + "********" + value.Substring(value.Length - 4);
});
// 处理邮箱
content = EmailRegex.Replace(content, match =>
{
string value = match.Value;
int atIndex = value.IndexOf('@');
string prefix = value.Substring(0, atIndex);
string suffix = value.Substring(atIndex);
return prefix[0] + "****" + suffix;
});
return content;
}
}
文件脱敏的完整流程实现
文件脱敏需要完成读取文件内容、调用脱敏方法、写入新文件三个步骤,同时要处理文件编码、异常捕获等生产环境常见问题。以下是完整的文件脱敏代码:
using System;
using System.IO;
using System.Text;
public class FileDesensitizationService
{
/// <summary>
/// 对指定文件进行脱敏处理,输出到新文件
/// </summary>
/// <param name="sourceFilePath">源文件路径</param>
/// <param name="targetFilePath">脱敏后文件路径</param>
/// <param name="encoding">文件编码,默认UTF8</param>
public static void DesensitizeFile(string sourceFilePath, string targetFilePath, Encoding encoding = null)
{
if (encoding == null)
{
encoding = Encoding.UTF8;
}
try
{
// 读取源文件全部内容
string fileContent = File.ReadAllText(sourceFilePath, encoding);
// 调用脱敏方法处理内容
string desensitizedContent = DataDesensitizationHelper.DesensitizeContent(fileContent);
// 写入目标文件,如果文件已存在则覆盖
File.WriteAllText(targetFilePath, desensitizedContent, encoding);
Console.WriteLine($"文件脱敏完成,结果已保存至:{targetFilePath}");
}
catch (FileNotFoundException)
{
Console.WriteLine($"源文件不存在:{sourceFilePath}");
}
catch (UnauthorizedAccessException)
{
Console.WriteLine($"没有文件操作权限,请检查路径权限");
}
catch (Exception ex)
{
Console.WriteLine($"文件脱敏过程出现异常:{ex.Message}");
}
}
}
生产环境脱敏注意事项
在生产环境使用上述方案时,还需要注意以下几点:
- 优先处理备份文件、日志文件等非实时文件,避免影响线上业务性能
- 敏感数据正则需要根据业务实际格式调整,比如部分特殊号段的手机号、境外身份证格式等
- 脱敏后的文件要设置严格的访问权限,避免脱敏结果再次泄露
- 对于超大文件,不要一次性读取全部内容,建议分块读取处理,减少内存占用
- 正式上线前要先在测试环境验证脱敏效果,确保不会误替换正常业务数据
使用示例
调用上述方法对生产环境的日志文件进行脱敏的示例代码如下:
class Program
{
static void Main(string[] args)
{
string sourceFile = @"C:logsproduction_202401.log";
string targetFile = @"C:logsproduction_desensitized.log";
// 执行文件脱敏
FileDesensitizationService.DesensitizeFile(sourceFile, targetFile);
}
}