通常,在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. }

最新文章

  1. 在c#中使用bitblt显示图片
  2. Android闹钟 AlarmManager的使用
  3. Alpha版本十天冲刺——Day 3
  4. ASP.NET 5中的ASP.NET Bundles跑到哪里去了?
  5. Java集合之ArrayList和LinkedList的实现原理以及Iterator详解
  6. 模板引擎逻辑语句处理之对单层for循环的处理
  7. IIS 和 各个协议
  8. @ResponseBody返回json时,json数据丢失或者报错
  9. 【LeetCode】98. Validate Binary Search Tree
  10. memcache图形化管理工具MemAdmin
  11. Java设计模式之原型设计模式
  12. Docker学习笔记之Docker 的简历
  13. [午间休息] - 午间codewars活跃脑袋
  14. 基于WMI的信息查询和编辑,按微软的说明一般都是
  15. 使用 jquery-autocomplete插件 完成文本框输入自动填充联想效果 解决兼容IE输入中文问题
  16. MTK 关闭安全模式
  17. HDU 2073 叠框
  18. c语言静态断言-定义自己的静态断言
  19. spring 启动完成后事件监听器处理
  20. vim 命令全

热门文章

  1. Nginx负载均衡配置
  2. java 22 - 10 多线程之两种代码实现方式的比较与区别
  3. window.execScript的兼容性写法
  4. python实现一个图灵机器人
  5. 实例讲解表单验证插件Validation的应用
  6. two sample ttest &amp; paired ttst
  7. 043医疗项目-模块四:采购单模块—采购单明细查询(Dao,Service,Action三层)
  8. 【点滴积累,厚积薄发】windows schedule task中.exe程序的路径问题等问题总结
  9. R统计分析处理
  10. es6+react环境搭建