如何在支持CSV导出导入往返功能的同时防止CSV注入?
处理CsvHelper防注入单引号的导入自动去除问题
针对你遇到的导出时添加防注入单引号、导入时无法自动去除且怕误删原始单引号的问题,这里有个精准的解决方案:
自定义类型转换器识别并去除系统添加的单引号
核心思路是:只有当字符串开头的单引号是导出时为防CSV注入自动添加的,才去除它;用户原始输入的单引号(比如内容本身以单引号开头但后面不是注入触发字符)则保留。
CsvHelper的InjectionOptions.Escape默认会给以-、+、=、@、\t、\r开头的内容添加前置单引号,我们可以基于这个规则自定义字符串转换器:
public class AntiInjectionStringConverter : StringConverter { // 匹配CsvHelper默认的注入触发前缀 private static readonly char[] InjectionTriggerChars = { '-', '+', '=', '@', '\t', '\r' }; public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData) { if (!string.IsNullOrEmpty(text) && text.StartsWith("'") && text.Length > 1) { var charAfterQuote = text[1]; // 仅当单引号后是注入触发字符时,才去除开头的单引号 if (InjectionTriggerChars.Contains(charAfterQuote)) { return text.Substring(1); } } // 其他情况返回原始内容 return base.ConvertFromString(text, row, memberMapData); } }
导入时启用转换器
在创建CsvConfiguration时注册这个自定义转换器即可:
var importConfig = new CsvConfiguration(CultureInfo.InvariantCulture) { // 你的其他导入配置(比如和导出一致的分隔符等) }; // 给字符串类型注册自定义转换器 importConfig.TypeConverterCache.AddConverter<string>(new AntiInjectionStringConverter()); using (var reader = new CsvReader(new StreamReader("用户上传的文件.csv"), importConfig)) { var updatedRecords = reader.GetRecords<你的数据模型类>().ToList(); }
为什么这个方案可行?
- 精准区分系统添加的单引号和用户原始单引号:只有单引号后紧跟注入触发字符时,才判定是导出时添加的防注入符号,避免误删用户输入的内容。
- 完全贴合CsvHelper的防注入逻辑:如果后续你修改了
InjectionOptions的触发前缀,只需要同步更新InjectionTriggerChars数组即可。
内容的提问来源于stack exchange,提问作者srk
相关产品推荐
相关产品推荐

