1.问题原因:我们在界面填写好数据之后并生成excel,如果数据中是以"=+-@"开头,那么在我们Excel里面显示的时候会出现CSV Injection问题。
2.如何解决:
- 2.1解决思路:首先生成Excel的workbook,之后再遍历这个workbook,如果遇到以这些特殊字符开头的数据,那么把这些数据拿到之后,在其前面加一个TAB键。
3.核心代码:
import org.apache.commons.lang.math.NumberUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
public static void formulaInjectionScan(Workbook wb)
{
if (null == wb)
{
return;
}
for (Sheet sheet : wb)
{
for (Row row : sheet)
{
for (Cell cell : row)
{
if (CellType.STRING == cell.getCellTypeEnum())
{
String cellVal = cell.getStringCellValue();
if (StringUtils.isNotBlank(cellVal) && cellVal.length() > 1 && !NumberUtils.isNumber(cellVal)
&& cellVal.matches(FORMULA_REGEX))
{
cell.setCellValue(TAB + cellVal);
}
}
}
}
}
}
4.引入新的问题:虽然CSV Injection问题处理好了,但是生产的Excel如果上传到我们的系统里面,那么界面上展示的跟CSV Injection相关的数据,这部分数据会显示TAB键,这不是用户想要的结果。
- 4.1处理引入新的问题:其实很简单,我们在上传Excel模板的接口中只需要把TAB打头的给过滤掉即可。
- 4.2 代码如下:
import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.lang3.StringUtils; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; public static void removePrefixedTabSpace(Workbook wb) { if (null == wb) { return; } for (Sheet sheet : wb) { for (Row row : sheet) { for (Cell cell : row) { if (CellType.STRING == cell.getCellTypeEnum()) { String cellVal = cell.getStringCellValue(); if (StringUtils.isNotBlank(cellVal) && cellVal.startsWith(String.valueOf(TAB))) { cell.setCellValue(cellVal.replaceFirst(String.valueOf(TAB), "")); } } } } } }