十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
这篇文章主要讲解了“Java如何用poi完成Excel导出数据脱敏”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java如何用poi完成Excel导出数据脱敏”吧!
网站建设哪家好,找成都创新互联公司!专注于网页设计、网站建设、微信开发、小程序定制开发、集团企业网站建设等服务项目。为回馈新老客户创新互联还提供了贡觉免费建站欢迎大家使用!
脱敏的百度百科的定义:是指对某些敏感信息通过脱敏规则进行数据的变形,实现敏感隐私数据的可靠保护。在涉及客户安全数据或者一些商业性敏感数据的情况下,在不违反系统规则条件下,对真实数据进行改造并提供测试使用,如身份证号、手机号、卡号、客户号等个人信息都需要进行数据脱敏。
这块如果严格按照定义,实现身份证等数据的变形,笔者还没实现,因为这个设计脱敏规则对应,需要用户指定规则,我们内部的脱敏系统还是有些逻辑在的,这里就不细说了,这次主要实现的是加*号【后期再加自定义吧,毕竟常见的都是星号】,方便导出数据的时候隐藏非必须字段。
维护数据
实现的功能主要分为三种:
1. 隐去收尾,适合固定长度,比如:手机号,身份证
2. 隐去部分,不固定长度,比如:姓名,地址
3. 隐去特定部分,特别表示保留,比如:邮箱
简单地实现的效果为
13112345678 --> 131****1234
张三 -->张*
罗纳尔迪尼奥 --> 罗纳***奥
wuyun@163.com -> w****@16com.com
脱敏效果
注解还是通过@Excel 的属性来实现的 ,在@Excel 这个地方加入了desensitizationRule属性,可以在desensitizationRule属性配置对应的格式遍可以得到对应的结果
/** * 数据脱敏规则 * 规则1: 采用保留头和尾的方式,中间数据加星号 * 如: 身份证 6_4 则保留 370101********1234 * 手机号 3_4 则保留 131****1234 * 规则2: 采用确定隐藏字段的进行隐藏,优先保留头 * 如: 姓名 1,3 表示最大隐藏3位,最小一位 * 李 --> * * 李三 --> 李* * 张全蛋 --> 张*蛋 * 李张全蛋 --> 李**蛋 * 尼古拉斯.李张全蛋 -> 尼古拉***张全蛋 * 规则3: 特殊符号后保留 * 如: 邮箱 1~@ 表示只保留第一位和@之后的字段 * afterturn@wupaas.com -> a********@wupaas.com * 复杂版本请使用接口 * {@link cn.afterturn.easypoi.handler.inter.IExcelDataHandler} */ public String desensitizationRule() default "";
可以根据注释看到,3个简单规则的使用方法,还是比较清晰的,主要是:
用下划线分隔的保留头尾的第一种格式
该格式首和尾都可以是0,表示不保留
用逗号分隔的隐藏部分数据的第二种格式
保留规则以对称为主
用~号来区分的,保留特殊字符后的格式的
如果存在多个特殊字符,只保留最后一位的数据
具体实现代码如下:
/** * 特定字符分隔,添加星号 * @param start * @param mark * @param value * @return */ private static String markSpilt(int start, String mark, String value) { if (value == null) { return null; } int end = value.lastIndexOf(mark); if (end <= start) { return value; } return StringUtils.left(value, start).concat(StringUtils.leftPad(StringUtils.right(value, value.length() - end), value.length() - start, "*")); } /** * 部分数据截取,优先对称截取 * @param start * @param end * @param value * @return */ private static String subMaxString(int start, int end, String value) { if (value == null) { return null; } if (start > end) { throw new IllegalArgumentException("start must less end"); } int len = value.length(); if (len <= start) { return StringUtils.leftPad("", len, "*"); } else if (len > start && len <= end) { if (len == 1) { return value; } if (len == 2) { return StringUtils.left(value, 1).concat("*"); } return StringUtils.left(value, 1).concat(StringUtils.leftPad(StringUtils.right(value, 1), StringUtils.length(value) - 1, "*")); } else { start = (int) Math.ceil((len - end + 0.0D) / 2); end = len - start - end; end = end == 0 ? 1 : end; return StringUtils.left(value, start).concat(StringUtils.leftPad(StringUtils.right(value, end), len - start, "*")); } } /** * 收尾截取数据 * @param start * @param end * @param value * @return */ private static String subStartEndString(int start, int end, String value) { if (value == null) { return null; } if (value.length() <= start + end) { return value; } return StringUtils.left(value, start).concat(StringUtils.leftPad(StringUtils.right(value, end), StringUtils.length(value) - start, "*")); }
使用起来也比较简单,通过简单的注解配置,就可以实现
@Excel(name = "姓名", desensitizationRule = "1,6") private String name; @Excel(name = "身份证", desensitizationRule = "6_4") private String card; @Excel(name = "手机号", desensitizationRule = "3_4") private String phone; @Excel(name = "邮箱", desensitizationRule = "3~@") private String email; // ---------------下面是生成excel的代码------- // 都是测试数据,就简单生成了部分 Listlist = new ArrayList<>(); for (int i = 0; i < 20; i++) { DesensitizationEntity entity = new DesensitizationEntity(); entity.setCard("37010119900101123" + i % 10); entity.setName("张三"); entity.setPhone("1311234567" + i % 10); entity.setEmail(i % 10 + "ttttt@afterturn.com"); list.add(entity); } Date start = new Date(); ExportParams params = new ExportParams("脱敏测试", "脱敏测试", ExcelType.XSSF); Workbook workbook = ExcelExportUtil.exportExcel(params, DesensitizationEntity.class, list); System.out.println(new Date().getTime() - start.getTime()); File savefile = new File("D:/home/excel/"); if (!savefile.exists()) { savefile.mkdirs(); } FileOutputStream fos = new FileOutputStream("D:/home/excel/ExcelDesensitizationTest.xlsx"); workbook.write(fos); fos.close();
生成的效果如下,可以看到几个场景都有所覆盖,基本上常用的字段也就
PS: 因为变种注解和注解可以通用,所以大家在使用变种注解的时候也可以使用这种方式来脱敏数据。
这里就不举例子了,只需要new ExcelExportEntity的之后调用setDesensitizationRule(rule),把对应的规则设置就好,规则和上面保持一致。
模板脱敏
目前从群里反应和问题数量看,模板已经是最常用的方式了,虽然我一致推荐注解,但明显模板比注解简单的,对代码的侵入一些,我自己写的特殊标签,也日益丰富了。
脱敏的标签取自:desensitizationRule 的两个单词的头两个字符 deru,用来表示这个数据需要脱敏。使用方法也比较简单deru:1_3,即deru:后面跟具体的规则,规则使用方式和上面介绍的 保持一致,这里就不重复赘述了,下面给大家看下例子:
/** * 这个包含两个规则 * 1. deru: 代表这个数据需要脱敏 * 2. dict: 代表这个需要调用字典接口转移 **/ deru:1_1;dict:mtype;t.supMaterialList.mtype
脱敏在标签处理级别中属于最低级,所有标签处理后,才会处理这个标签,和他的书写顺序无关,比如上面的例子他写着第一个,也是先处理了字典之后才处理标签。
核心代码如下:
/** * 根据模板解析函数获取值 * @param funStr * @param map * @return */ private Object getValByHandler(String funStr,Mapmap, Cell cell) throws Exception { // step 2. 判断是否含有解析函数 if (isHasSymbol(funStr, NUMBER_SYMBOL)) { funStr = funStr.replaceFirst(NUMBER_SYMBOL, ""); } boolean isStyleBySelf = false; if (isHasSymbol(funStr, STYLE_SELF)) { isStyleBySelf = true; funStr = funStr.replaceFirst(STYLE_SELF, ""); } boolean isDict = false; String dict = null; if (isHasSymbol(funStr, DICT_HANDLER)) { isDict = true; dict = funStr.substring(funStr.indexOf(DICT_HANDLER) + 5).split(";")[0]; funStr = funStr.replaceFirst(DICT_HANDLER, ""); funStr = funStr.replaceFirst(dict + ";", ""); } boolean isI18n = false; if (isHasSymbol(funStr, I18N_HANDLER)) { isI18n = true; funStr = funStr.replaceFirst(I18N_HANDLER, ""); } //这里判断是否包含注解规则,如果有注解规则就把注解规则挑出来,然后删除掉规则 boolean isDern = false; String dern = null; if (isHasSymbol(funStr, DESENSITIZATION_RULE)) { isDern = true; dern = funStr.substring(funStr.indexOf(DESENSITIZATION_RULE) + 5).split(";")[0]; funStr = funStr.replaceFirst(DESENSITIZATION_RULE, ""); funStr = funStr.replaceFirst(dern + ";", ""); } if (isHasSymbol(funStr, MERGE)) { String mergeStr = PoiPublicUtil.getElStr(funStr,MERGE); funStr = funStr.replace(mergeStr, ""); mergeStr = mergeStr.replaceFirst(MERGE, ""); try { int colSpan = (int)Double.parseDouble(PoiPublicUtil.getRealValue(mergeStr, map).toString()); PoiMergeCellUtil.addMergedRegion(cell.getSheet(), cell.getRowIndex(), cell.getRowIndex() , cell.getColumnIndex(), cell.getColumnIndex() + colSpan - 1); } catch (Exception e) { LOGGER.error(e.getMessage(),e); } } Object obj = funStr.indexOf(START_STR) == -1 ? eval(funStr, map) : PoiPublicUtil.getRealValue(funStr, map); if (isDict) { obj = dictHandler.toName(dict, null, funStr, obj); } if (isI18n) { obj = i18nHandler.getLocaleName(obj.toString()); } // 这里就是调用脱敏规则,和注解是一个工具类,所以规则一致 if (isDern) { obj = PoiDataDesensitizationUtil.desensitization(dern,obj); } return obj; }
给大家看下模板跑出来的效果:
最后结果
感谢各位的阅读,以上就是“Java如何用poi完成Excel导出数据脱敏”的内容了,经过本文的学习后,相信大家对Java如何用poi完成Excel导出数据脱敏这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是创新互联,小编将为大家推送更多相关知识点的文章,欢迎关注!