通常,在WEB系统中,上传文件时都需要做文件的类型校验,大致有如下几种方法:

1. 通过后缀名,如exe,jpg,bmp,rar,zip等等。

2. 通过读取文件,获取文件的Content-type来判断。

3. 通过读取文件流,根据文件流中特定的一些字节标识来区分不同类型的文件。

4. 若是图片,则通过缩放来判断,可以缩放的为图片,不可以的则不是。

然而,在安全性较高的业务场景中,1,2两种方法的校验会被轻易绕过。

1. 伪造后缀名,如图片的,非常容易修改。

2. 伪造文件的Content-type,这个稍微复杂点,

3.较安全,但是要读取文件,并有16进制转换等操作,性能稍差,但能满足一定条件下对安全的要求,所以建议使用。

但是文件头的信息也可以伪造,截图如下,对于图片可以采用图片缩放或者获取图片宽高的方法避免伪造头信息漏洞。

  1. package com.nfschina.utils.file;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.util.HashMap;
  5. import java.util.Iterator;
  6. import java.util.Map;
  7. import java.util.Map.Entry;
  8. import com.nfschina.utils.BaseException;
  9. /***********************************************************************
  10. *
  11. * Description: 主要用于判断文件的类型
  12. *
  13. ***********************************************************************/
  14. public class FileTools {
  15. public final static Map<String, String> FILE_TYPE_MAP = new HashMap<String, String>();
  16. /*-----------------------------目前可以识别的类型----------------------------*/
  17. private static void getAllFileType()
  18. {
  19. FILE_TYPE_MAP.put("jpg", "FFD8FF"); //JPEG
  20. FILE_TYPE_MAP.put("png", "89504E47"); //PNG
  21. FILE_TYPE_MAP.put("gif", "47494638"); //GIF
  22. FILE_TYPE_MAP.put("tif", "49492A00"); //TIFF
  23. FILE_TYPE_MAP.put("bmp", "424D"); //Windows Bitmap
  24. FILE_TYPE_MAP.put("dwg", "41433130"); //CAD
  25. FILE_TYPE_MAP.put("html", "68746D6C3E"); //HTML
  26. FILE_TYPE_MAP.put("rtf", "7B5C727466"); //Rich Text Format
  27. FILE_TYPE_MAP.put("xml", "3C3F786D6C");
  28. FILE_TYPE_MAP.put("zip", "504B0304");
  29. FILE_TYPE_MAP.put("rar", "52617221");
  30. FILE_TYPE_MAP.put("psd", "38425053"); //PhotoShop
  31. FILE_TYPE_MAP.put("eml", "44656C69766572792D646174653A"); //Email [thorough only]
  32. FILE_TYPE_MAP.put("dbx", "CFAD12FEC5FD746F"); //Outlook Express
  33. FILE_TYPE_MAP.put("pst", "2142444E"); //Outlook
  34. FILE_TYPE_MAP.put("office", "D0CF11E0"); //office类型,包括doc、xls和ppt
  35. FILE_TYPE_MAP.put("mdb", "000100005374616E64617264204A"); //MS Access
  36. FILE_TYPE_MAP.put("wpd", "FF575043"); //WordPerfect
  37. FILE_TYPE_MAP.put("eps", "252150532D41646F6265");
  38. FILE_TYPE_MAP.put("ps", "252150532D41646F6265");
  39. FILE_TYPE_MAP.put("pdf", "255044462D312E"); //Adobe Acrobat
  40. FILE_TYPE_MAP.put("qdf", "AC9EBD8F"); //Quicken
  41. FILE_TYPE_MAP.put("pwl", "E3828596"); //Windows Password
  42. FILE_TYPE_MAP.put("wav", "57415645"); //Wave
  43. FILE_TYPE_MAP.put("avi", "41564920");
  44. FILE_TYPE_MAP.put("ram", "2E7261FD"); //Real Audio
  45. FILE_TYPE_MAP.put("rm", "2E524D46"); //Real Media
  46. FILE_TYPE_MAP.put("mpg", "000001BA"); //
  47. FILE_TYPE_MAP.put("mov", "6D6F6F76"); //Quicktime
  48. FILE_TYPE_MAP.put("asf", "3026B2758E66CF11"); //Windows Media
  49. FILE_TYPE_MAP.put("mid", "4D546864"); //MIDI (mid)
  50. }
  51. /**
  52. * 通过读取文件头部获得文件类型
  53. * @param file
  54. * @return 文件类型
  55. * @throws BaseException
  56. */
  57. public static String getFileType(File file) throws BaseException{
  58. getAllFileType();
  59. String fileExtendName = null;
  60. FileInputStream is;
  61. try {
  62. is = new FileInputStream(file);
  63. byte[] b = new byte[16];
  64. is.read(b,0, b.length);
  65. String filetypeHex = String.valueOf(bytesToHexString(b));
  66. Iterator<Entry<String, String>> entryiterator = FILE_TYPE_MAP.entrySet().iterator();
  67. while (entryiterator.hasNext()) {
  68. Entry<String,String> entry = entryiterator.next();
  69. String fileTypeHexValue = entry.getValue();
  70. if (filetypeHex.toUpperCase().startsWith(fileTypeHexValue)) {
  71. fileExtendName = entry.getKey();
  72. if(fileExtendName.equals("office")) {
  73. fileExtendName = getOfficeFileType(is);
  74. }
  75. is.close();
  76. break;
  77. }
  78. }
  79. // 如果不是上述类型,则判断扩展名
  80. if(fileExtendName == null)
  81. {
  82. String fileName = file.getName();
  83. // 如果无扩展名,则直接返回空串
  84. if(-1 == fileName.indexOf("."))
  85. {
  86. return "";
  87. }
  88. // 如果有扩展名,则返回扩展名
  89. return fileName.substring(fileName.indexOf(".") + 1);
  90. }
  91. is.close();
  92. return fileExtendName;
  93. } catch (Exception exception) {
  94. throw new BaseException(exception.getMessage(), exception);
  95. }
  96. }
  97. /**
  98. * 判断office文件的具体类型
  99. * @param fileInputStream
  100. * @return office文件具体类型
  101. * @throws BaseException
  102. */
  103. private static String getOfficeFileType(FileInputStream fileInputStream) throws BaseException{
  104. String officeFileType = "doc";
  105. byte[] b = new byte[512];
  106. try {
  107. fileInputStream.read(b, 0, b.length);
  108. String filetypeHex = String.valueOf(bytesToHexString(b));
  109. String flagString = filetypeHex.substring(992, filetypeHex.length());
  110. if(flagString.toLowerCase().startsWith("eca5c")){
  111. officeFileType = "doc";
  112. } else if(flagString.toLowerCase().startsWith("fdffffff09")){
  113. officeFileType = "xls";
  114. } else if(flagString.toLowerCase().startsWith("09081000000")){
  115. officeFileType = "xls";
  116. } else {
  117. officeFileType = "ppt";
  118. }
  119. return officeFileType;
  120. } catch (Exception exception) {
  121. throw new BaseException(exception.getMessage(), exception);
  122. }
  123. }
  124. /**
  125. * 获得文件头部字符串
  126. * @param src
  127. * @return
  128. */
  129. private static String bytesToHexString(byte[] src){
  130. StringBuilder stringBuilder = new StringBuilder();
  131. if (src == null || src.length <= 0) {
  132. return null;
  133. }
  134. for (int i = 0; i < src.length; i++) {
  135. int v = src[i] & 0xFF;
  136. String hv = Integer.toHexString(v);
  137. if (hv.length() < 2) {
  138. stringBuilder.append(0);
  139. }
  140. stringBuilder.append(hv);
  141. }
  142. return stringBuilder.toString();
  143. }
  144. public static void main(String[] args)
  145. {
  146. File file = new File("E:/新闻公告.pdm");
  147. FileInputStream is;
  148. try{
  149. is = new FileInputStream(file);
  150. byte[] b = new byte[16];
  151. is.read(b,0, b.length);
  152. //            String filetypeHex = String.valueOf(bytesToHexString(b));
  153. String fileName = file.getName();
  154. System.out.println(fileName.substring(fileName.indexOf(".") + 1));
  155. }catch(Exception e)
  156. {
  157. e.printStackTrace();
  158. }
  159. }

JAVA对文件类型的校验的更多相关文章

  1. Java判断文件类型

    通常,在WEB系统中,上传文件时都需要做文件的类型校验,大致有如下几种方法: 1. 通过后缀名,如exe,jpg,bmp,rar,zip等等. 2. 通过读取文件,获取文件的Content-type来 ...

  2. JAVA生成文件的md5校验值

    这里使用了lombok打印日志,也可以不用 import java.io.File; import java.io.FileInputStream; import java.io.IOExceptio ...

  3. JAVA计算文件的crc32校验码

    import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java ...

  4. Java根据字节数据判断文件类型

    通常,在WEB系统中,上传文件时都需要做文件的类型校验,大致有如下几种方法: 1. 通过后缀名,如exe,jpg,bmp,rar,zip等等. 2. 通过读取文件,获取文件的Content-type来 ...

  5. [原创]java WEB学习笔记81:Hibernate学习之路--- 对象关系映射文件(.hbm.xml):hibernate-mapping 节点,class节点,id节点(主键生成策略),property节点,在hibernate 中 java类型 与sql类型之间的对应关系,Java 时间和日期类型的映射,Java 大对象类型 的 映射 (了解),映射组成关系

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  6. java读取各类型的文件

    java读取各类型的文件 用到的几个包 bcmail-jdk14-132.jar/bcprov-jdk14-132.jar/checkstyle-all-4.2.jar/FontBox-0.1.0-d ...

  7. Android 虚拟机Dalvik、Android各种java包功能、Android相关文件类型、应用程序结构分析、ADB

    Android虚拟机Dalvik Dalvik冲击 随着Google 的AndroidSDK 的发布,关于它的API 以及在移动电话领域所带来的预期影响这些方面的讨论不胜枚举.不过,其中的一个话题在J ...

  8. 用java流方式判断文件类型

    这个方法只能在有限的范围内有效.并不是万金油 比如 图片类型判断,音频文件格式判断,视频文件格式判断等这种肯定是2进制且专业性很强的文件类型判断. 下面给出完整版代码 首先是文件类型枚取 packag ...

  9. 通过后缀名和MIME-TYPE检查实现文件类型校验

    前言 文件上传是一个在开发中很常见的需求场景,通常出于安全考虑,我们会对上传的文件进行类型校验,其中常见的有后缀名校验,mime-type校验 话不多说,直接上代码 1.首先定义允许上传的文件类型白名 ...

随机推荐

  1. CocoaPods 哪些事

    一.CocoaPods的介绍 什么是CocoaPods CocoaPods是OS X和iOS下的一个第三类库管理工具,通过CocoaPods工具我们可以为项目添加被称为“Pods”的依赖库(这些类库必 ...

  2. 使用 JavaScript File API 实现文件上传

    概述 以往对于基于浏览器的应用而言,访问本地文件都是一件头疼的事情.虽然伴随着 Web 2.0 应用技术的不断发展,JavaScript 正在扮演越来越重要的角色,但是出于安全性的考虑,JavaScr ...

  3. Meet Python: little notes 2

    From this blog I will turn to Markdown for original writing. Source: http://www.liaoxuefeng.com/ ♥ l ...

  4. Java 集合系列17之 TreeSet详细介绍(源码解析)和使用示例

    概要 这一章,我们对TreeSet进行学习.我们先对TreeSet有个整体认识,然后再学习它的源码,最后再通过实例来学会使用TreeSet.内容包括:第1部分 TreeSet介绍第2部分 TreeSe ...

  5. android 打Patch的方法 .

    http://blog.csdn.net/sunyubo458/article/details/6680840 作为程序员,了解diff&patch命 令是非常必要的.比如说我们发现某个项目有 ...

  6. httpserver

    改了下 # -*- coding:utf-8 -*- from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler HOST = &quo ...

  7. java基础:所有参数皆是按值参数

    c#中对于参数的传递,有二种处理方式,默认情况下:值类型的参数,按值传递(即:方法体内的参数是原值的副本):引用类型的参数,"加ref关键字后“,按引用传递(即:方法体内的参数,是对象的指针 ...

  8. realmswift的使用

    官网:https://realm.io/ 1.说下数据库迁移的问题: 在func application(application: UIApplication, didFinishLaunchingW ...

  9. Qt5 新特性

    Qt 5 已经临近发布,其最大的特点就是模块化.将原来庞大的模块更细分为不同的部分,同时,一个大版本的升级,当然少不了添加.删除各个功能类.文本简单介绍 Qt5 的特性,其具体内容来自 Qt5 官方 ...

  10. opencv5-objdetect之级联分类器

    这是<opencv2.4.9tutorial.pdf>的objdetect module的唯一一个例子. 在opencv中进行人脸或者人眼 或者身体的检测 首先就是训练好级联分类器,然后就 ...