对外接口支持文件上传功能时,为避免有人恶意上传有毒或者篡改程序的脚本,需要对上传的文件添加安全性校验。

文章目录

  • 1.文件后缀校验
  • 2.校验文件头
    • 1.使用枚举类去校验
      • 1.魔数枚举类
      • 2.获取文件头,并校验是否为Excel
    • 2.FileMagic校验文件头
  • 3.校验文件大小
  • 4.示例

1.文件后缀校验

文件首先校验直观文件上传格式,校验文件后缀是否符合业务要求。以MultipartFile类为例

        String fileName = file.getOriginalFilename();if (Strings.isEmpty(fileName)) {throw new RuntimeException("文件名未找到");}String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);if (!Objects.equal(suffix, "xls") && !Objects.equal(suffix, "xlsx")) {throw new RuntimeException("文件类型不正确,需要为xls或者xlsx");}

2.校验文件头

由于文件后缀可能涉及到篡改的情况出现,因此需要校验文件的魔数,也就是文件头。无论这个文件是否修改文件后缀,这个文件的文件头是不会改变的。下面是常用的文件头格式:

1.使用枚举类去校验

JPEG (jpg),文件头:FFD8FFE1
PNG (png),文件头:89504E47
GIF (gif),文件头:47494638
TIFF (tif),文件头:49492A00
Windows Bitmap (bmp),文件头:424D
CAD (dwg),文件头:41433130
Adobe Photoshop (psd),文件头:38425053
Rich Text Format (rtf),文件头:7B5C727466
XML (xml),文件头:3C3F786D6C
HTML (html),文件头:68746D6C3E
Email [thorough only] (eml),文件头:44656C69766572792D646174653A
Outlook Express (dbx),文件头:CFAD12FEC5FD746F
Outlook (pst),文件头:2142444E
MS Word/Excel (xls.or.doc),文件头:D0CF11E0
MS Access (mdb),文件头:5374616E64617264204A
WordPerfect (wpd),文件头:FF575043
Postscript (eps.or.ps),文件头:252150532D41646F6265
Adobe Acrobat (pdf),文件头:255044462D312E
Quicken (qdf),文件头:AC9EBD8F
Windows Password (pwl),文件头:E3828596
ZIP Archive (zip),文件头:504B0304
RAR Archive (rar),文件头:52617221
Wave (wav),文件头:57415645
AVI (avi),文件头:41564920
Real Audio (ram),文件头:2E7261FD
Real Media (rm),文件头:2E524D46
MPEG (mpg),文件头:000001BA
MPEG (mpg),文件头:000001B3
Quicktime (mov),文件头:6D6F6F76
Windows Media (asf),文件头:3026B2758E66CF11
MIDI (mid),文件头:4D546864

使用上面的文件头去校验的代码示例(这段代码参考:Java 实战系列·Magic 魔数获取文件类型):

1.魔数枚举类

public enum FileType {/*** JPEG*/JPEG("JPEG", "FFD8FF"),/*** PNG*/PNG("PNG", "89504E47"),/*** GIF*/GIF("GIF", "47494638"),/*** TIFF*/TIFF("TIFF", "49492A00"),/*** Windows bitmap*/BMP("BMP", "424D"),/*** CAD*/DWG("DWG", "41433130"),/*** Adobe photoshop*/PSD("PSD", "38425053"),/*** Rich Text Format*/RTF("RTF", "7B5C727466"),/*** XML*/XML("XML", "3C3F786D6C"),/*** HTML*/HTML("HTML", "68746D6C3E"),/*** Outlook Express*/DBX("DBX", "CFAD12FEC5FD746F "),/*** Outlook*/PST("PST", "2142444E"),/*** doc;xls;dot;ppt;xla;ppa;pps;pot;msi;sdw;db*/OLE2("OLE2", "0xD0CF11E0A1B11AE1"),/*** Microsoft Word/Excel*/XLS_DOC("XLS_DOC", "D0CF11E0"),/*** Microsoft Access*/MDB("MDB", "5374616E64617264204A"),/*** Word Perfect*/WPB("WPB", "FF575043"),/*** Postscript*/EPS_PS("EPS_PS", "252150532D41646F6265"),/*** Adobe Acrobat*/PDF("PDF", "255044462D312E"),/*** Windows Password*/PWL("PWL", "E3828596"),/*** ZIP Archive*/ZIP("ZIP", "504B0304"),/*** ARAR Archive*/RAR("RAR", "52617221"),/*** WAVE*/WAV("WAV", "57415645"),/*** AVI*/AVI("AVI", "41564920"),/*** Real Audio*/RAM("RAM", "2E7261FD"),/*** Real Media*/RM("RM", "2E524D46"),/*** Quicktime*/MOV("MOV", "6D6F6F76"),/*** Windows Media*/ASF("ASF", "3026B2758E66CF11"),/*** MIDI*/MID("MID", "4D546864");private String key;private String value;FileType(String key, String value) {this.key = key;this.value = value;}public String getValue() {return value;}public String getKey() {return key;}
}

2.获取文件头,并校验是否为Excel

public class FileUtil {/*** 获取文件投** @param filePath 文件路径* @return 16 进制的文件投信息** @throws IOException*/private static String getFileHeader(String filePath) throws IOException {byte[] b = new byte[28];InputStream inputStream = new FileInputStream(filePath);inputStream.read(b, 0, 28);inputStream.close();return bytes2hex(b);}/*** 将字节数组转换成16进制字符串*/private static String bytes2hex(byte[] src) {StringBuilder stringBuilder = new StringBuilder("");if (src == null || src.length <= 0) {return null;}for (byte b : src) {int v = b & 0xFF;String hv = Integer.toHexString(v);if (hv.length() < 2) {stringBuilder.append(0);}stringBuilder.append(hv);}return stringBuilder.toString();}/*** 校验是否为excel** @param filePath 文件路径* @return 文件类型** @throws IOException*/public static boolean checkIsExcel(String filePath) throws IOException {String fileHead = getFileHeader(filePath);if (null == fileHead || fileHead.length() == 0) {return false;}//校验是否为xls或者xlsx文件if (Objects.equal(fileHead, FileType.OLE2.getValue()) || Objects.equal(fileHead, FileType.XLS_DOC.getValue())) {return true;}return false;}
}

除了用上面的魔数头去校验,也可以用poi提供的枚举类FileMagic工具类去校验:

2.FileMagic校验文件头

FileMagic魔数值解释:

    OLE2(-2226271756974174256L),   //xlsOOXML(new int[]{80, 75, 3, 4}), //xlsx, OOXML全称是Office Open XML,OOXML是由微软公司为Office 2007产品开发的技术规范,现已成为国际文档格式标准,兼容前国际标准ODF(Open Document Format)和中国文档标准UOF(Unified Office document Format)。XML(new int[]{60, 63, 120, 109, 108}),  //xmlBIFF2(new int[]{9, 0, 4, 0, 0, 0, 63, 0}), //Excel 2 现在office已经不支持BIFF3(new int[]{9, 2, 6, 0, 0, 0, 63, 0}),//Excel 3现在office已经不支持BIFF4(new byte[][]{{9, 4, 6, 0, 0, 0, 63, 0}, {9, 4, 6, 0, 0, 0, 0, 1}}),//Excel 4 现在office已经不支持MSWRITE(new byte[][]{{49, -66, 0, 0}, {50, -66, 0, 0}}),  //微软原来的写入流,这个不清楚是否还能使用。RTF(new String[]{"{\\rtf"}),  //rtfPDF(new String[]{"%PDF"}), //pdfHTML(new String[]{"<!DOCTYP", "<html", "\n\r<html", "\r\n<html", "\r<html", "\n<html", "<HTML", "\r\n<HTML", "\n\r<HTML", "\r<HTML", "\n<HTML"}),  //HTMLWORD2(new int[]{219, 165, 45, 0}),//wordJPEG(new byte[][]{{-1, -40, -1, -37}, {-1, -40, -1, -32, 63, 63, 74, 70, 73, 70, 0, 1}, {-1, -40, -1, -18}, {-1, -40, -1, -31, 63, 63, 69, 120, 105, 102, 0, 0}}),//图片验证,jpeg格式GIF(new String[]{"GIF87a", "GIF89a"}),//图片验证,gif格式PNG(new int[]{137, 80, 78, 71, 13, 10, 26, 10}),//图片验证,png格式TIFF(new String[]{"II*\u0000", "MM\u0000*"}),//图片验证,tiff格式WMF(new int[]{215, 205, 198, 154}),//图片验证,wmf格式EMF(new int[]{1, 0, 0, 0, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 32, 69, 77, 70}),//图片验证,emf格式BMP(new int[]{66, 77}),//图片验证,nmp格式UNKNOWN(new byte[][]{new byte[0]});//未知魔数

使用魔数校验Excel文件代码:

 private static boolean checkIsExcel(InputStream inputStream) throws IOException {//获取文件流的文件头FileMagic fileMagic = FileMagic.valueOf(inputStream);//判断Excel文件头是否符合xls或者xlsxif (Objects.equal(fileMagic, FileMagic.OLE2) || Objects.equal(fileMagic, FileMagic.OOXML)) {return true;}return false;}

3.校验文件大小

为了避免上传过大文件,影响服务器性能以及带宽。需要对文件大小进行校验,具体文件大小控制以业务为主。

4.示例

以校验Excel文件为例:

 /*** 校验文件** @param file 文件* @param fileMaxSize  文件大小限制*/public static void checkExcel(MultipartFile file, Double fileMaxSize) {// 文件类型判断 - 校验文件后缀String fileName = file.getOriginalFilename();if (Strings.isEmpty(fileName)) {throw new RuntimeException("文件名未找到");}String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);if (!Objects.equal(suffix, "xls") && !Objects.equal(suffix, "xlsx")) {throw new RuntimeException("文件类型不正确,需要为xls或者xlsx");}// 文件类型判断 - 校验文件头内容try (InputStream inputStream = file.getInputStream()) {// 获取到上传文件的文件头信息boolean isExcel = checkIsExcel(inputStream);if (!isExcel) {throw new RuntimeException("文件类型不正确,原文件类型需要为xls");}} catch (IOException e) {log.error("Get file input stream failed.", e);throw new RuntimeException("文件上传失败");}// 文件大小校验 - 单位:MBlong fileBytes = file.getSize();double fileSize = (double) fileBytes / 1048576;if (fileSize <= 0) {throw new RuntimeException("文件内容为空");}if (fileSize > fileMaxSize) {throw new RuntimeException("文件上传内容大小超出限制");}}/*** 校验文件头** @param inputStream* @return** @throws IOException*/private static boolean checkIsExcel(InputStream inputStream) throws IOException {FileMagic fileMagic = FileMagic.valueOf(inputStream);if (Objects.equal(fileMagic, FileMagic.OLE2) || Objects.equal(fileMagic, FileMagic.OOXML)) {return true;}return false;}

10-java实现对上传文件做安全性检查相关推荐

  1. java scp 上传文件_java基于Scp实现Linux下远程获取、上传文件

    前不久在项目开发中遇上的一个需求:需要在B机器上将A机器某路径下的文件拷贝到B机器上做保存. 简单分析下来,自己的理解就是:一个RPC,主要就是解决跨域传输文件的问题.在提前能拿到A机器的IP.Por ...

  2. java swf 上传文件_Flash上传组件之SWFUpload文件上传

    SWFUpload是一个客户端文件上传工具,最初由Vinterwebb.se开发,它通过整合Flash与JavaScript技术为WEB开发者提供了一个具有丰富功能继而超越传统标签的文件上传模式. 由 ...

  3. spring boot配置对上传文件的大小限制

    spring boot配置对上传文件的大小限制 spring-boot 2.0之前 Spring Boot1.4版本后配置更改为(默认单个文件最大1Mb,单次请求文件总数大小最大10Mb): spri ...

  4. java flex 上传文件_使用Flex和java servlet上传文件

    资源都是来自网上.本实例将展示使用Flex和java servlet上传文件. 事前准备就是到http://commons.apache.org 下载common-fileupload-1.1.1.j ...

  5. layui表单加文件 php_layui框架实现文件上传及TP3.2.3(thinkPHP)对上传文件进行后台处理操作示例...

    本文实例讲述了layui框架实现文件上传及TP3.2.3对上传文件进行后台处理操作.分享给大家供大家参考,具体如下: layui框架是1.0.9版本.. 首先html页面代码如下: js代码如下: l ...

  6. Java服务器与客户端传文件,java实现上传文件到服务器和客户端.pdf

    java实实现现上上传传文文件件到到服服务务器器和和客客户户端端 这篇文章主要为大家详细介绍了java实现上传文件到服务器和客户端,具有一定的参考价值,感兴趣的小伙伴们 以参考一下 JAVA编写一个 ...

  7. java 如何上传文件_java如何上传文件 | 快速入门

    关键词:路径 上传文件 表单 文件 上传 存放 后台 定义 代码 数据 详细内容 相关文章 中文网 控制台 字段 一:准备好前台页面Upload.html 表单 action=上传文件后台接口 met ...

  8. java 获取上传文件的格式_js和java获取上传文件的文件名以及上传文件格式判断...

    js获取文件名: //校验 function check(){ var fileType = $("#template").val(); //判断后缀是不是需要的文件类型 if(f ...

  9. Java 对上传文件进行魔数校验

    魔数这个词在不同领域代表不同的含义.在计算机领域,魔数有两个含义,一指用来判断文件类型的魔数(magic number):二指程序代码中的魔数,也称魔法值. 不是所有文件都有文件头的.一个.txt类型 ...

最新文章

  1. Jeff Dean| 面向系统的机器学习和面向机器学习的系统
  2. 50题真 • 一文入门TensorFlow2.x
  3. 【web安全】第三弹:web攻防平台pentester安装及XSS部分答案解析
  4. Mybatis之占位符与拼接符
  5. linux下的crontab
  6. JPA和Hibernate级联类型的初学者指南
  7. php调用.net webservice,PHP调用.NET的WebService 简单实例
  8. 诗与远方:无题(三十八)
  9. php全选帖子删除,用PHP实现全选全删
  10. fiddler证书 iphone_【详细】Mac使用Fiddler实现IPhone抓包(支持https)
  11. Oracle入门教程,新手必读
  12. 【eclipse】导入/导出开发环境(包括编辑器字体颜色大小等)
  13. 无线充QI协议之TX与RX通讯方式篇
  14. HTTP Live Streaming
  15. Python爬虫 爬取dota2官网英雄缺少英雄
  16. 阅读《Keyword-Guided Neural Conversational Model》
  17. Notes Fifteenth Day-渗透攻击-红队-内部信息搜集
  18. 六个参数帮你全面了解固态硬盘
  19. 如何下载blob:https://www.bilibili.com/的视频
  20. Dive_into_Deep_Learning

热门文章

  1. oraclestddev函数_Oracle分析函数的应用(原创)
  2. Kaniko构建镜像
  3. 飞链云版图安全食用指南 AI绘画超详细保姆级新手教程
  4. 关于Flappy bird中水管与小鸟的碰撞
  5. catia CAA 获取catia版本
  6. 玩诈欺的小杉(详细解析+代码)
  7. 移动端测试Monkey测试
  8. R语言建立决策树模型(movie数据集)
  9. finalshell 忘记密码怎么办?
  10. (附源码)mysql+ssm学校疫情服务平台 毕业设计 291202