zoukankan      html  css  js  c++  java
  • JAVA对文件类型的校验

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

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

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

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

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

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

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

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

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

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

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