JAVA对文件类型的校验

通常,在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. }
上一篇:win10 64位安装memcache扩展和开启redis扩展


下一篇:linux php 安装 memcache 扩展