Java判断文件类型
通常,在WEB系统中,上传文件时都需要做文件的类型校验,大致有如下几种方法:
1. 通过后缀名,如exe,jpg,bmp,rar,zip等等。
2. 通过读取文件,获取文件的Content-type来判断。
3. 通过读取文件流,根据文件流中特定的一些字节标识来区分不同类型的文件。
4. 若是图片,则通过缩放来判断,可以缩放的为图片,不可以的则不是。
然而,在安全性较高的业务场景中,1,2两种方法的校验会被轻易绕过。
1. 伪造后缀名,如图片的,非常容易修改。
2. 伪造文件的Content-type,这个稍微复杂点,为了直观,截图如下:

3.较安全,但是要读取文件,并有16进制转换等操作,性能稍差,但能满足一定条件下对安全的要求,所以建议使用。
但是文件头的信息也可以伪造,截图如下,对于图片可以采用图片缩放或者获取图片宽高的方法避免伪造头信息漏洞。

被伪装成gif的恶意图片文件
对应的Java代码如下:
- package apistudy;
- import java.awt.image.BufferedImage;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileNotFoundException;
- import java.io.IOException;
- import java.io.InputStream;
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.Map;
- import java.util.Map.Entry;
- import javax.imageio.ImageIO;
- import javax.imageio.ImageReader;
- import javax.imageio.stream.ImageInputStream;
- public class FileTypeTest
- {
- public final static Map<String, String> FILE_TYPE_MAP = new HashMap<String, String>();
- private FileTypeTest(){}
- static{
- getAllFileType(); //初始化文件类型信息
- }
- /**
- * Created on 2010-7-1
- * <p>Discription:[getAllFileType,常见文件头信息]</p>
- * @author:[shixing_11@sina.com]
- */
- private static void getAllFileType()
- {
- FILE_TYPE_MAP.put("jpg", "FFD8FF"); //JPEG (jpg)
- FILE_TYPE_MAP.put("png", "89504E47"); //PNG (png)
- FILE_TYPE_MAP.put("gif", "47494638"); //GIF (gif)
- FILE_TYPE_MAP.put("tif", "49492A00"); //TIFF (tif)
- FILE_TYPE_MAP.put("bmp", "424D"); //Windows Bitmap (bmp)
- FILE_TYPE_MAP.put("dwg", "41433130"); //CAD (dwg)
- FILE_TYPE_MAP.put("html", "68746D6C3E"); //HTML (html)
- FILE_TYPE_MAP.put("rtf", "7B5C727466"); //Rich Text Format (rtf)
- FILE_TYPE_MAP.put("xml", "3C3F786D6C");
- FILE_TYPE_MAP.put("zip", "504B0304");
- FILE_TYPE_MAP.put("rar", "52617221");
- FILE_TYPE_MAP.put("psd", "38425053"); //Photoshop (psd)
- FILE_TYPE_MAP.put("eml", "44656C69766572792D646174653A"); //Email [thorough only] (eml)
- FILE_TYPE_MAP.put("dbx", "CFAD12FEC5FD746F"); //Outlook Express (dbx)
- FILE_TYPE_MAP.put("pst", "2142444E"); //Outlook (pst)
- FILE_TYPE_MAP.put("xls", "D0CF11E0"); //MS Word
- FILE_TYPE_MAP.put("doc", "D0CF11E0"); //MS Excel 注意:word 和 excel的文件头一样
- FILE_TYPE_MAP.put("mdb", "5374616E64617264204A"); //MS Access (mdb)
- FILE_TYPE_MAP.put("wpd", "FF575043"); //WordPerfect (wpd)
- FILE_TYPE_MAP.put("eps", "252150532D41646F6265");
- FILE_TYPE_MAP.put("ps", "252150532D41646F6265");
- FILE_TYPE_MAP.put("pdf", "255044462D312E"); //Adobe Acrobat (pdf)
- FILE_TYPE_MAP.put("qdf", "AC9EBD8F"); //Quicken (qdf)
- FILE_TYPE_MAP.put("pwl", "E3828596"); //Windows Password (pwl)
- FILE_TYPE_MAP.put("wav", "57415645"); //Wave (wav)
- FILE_TYPE_MAP.put("avi", "41564920");
- FILE_TYPE_MAP.put("ram", "2E7261FD"); //Real Audio (ram)
- FILE_TYPE_MAP.put("rm", "2E524D46"); //Real Media (rm)
- FILE_TYPE_MAP.put("mpg", "000001BA"); //
- FILE_TYPE_MAP.put("mov", "6D6F6F76"); //Quicktime (mov)
- FILE_TYPE_MAP.put("asf", "3026B2758E66CF11"); //Windows Media (asf)
- FILE_TYPE_MAP.put("mid", "4D546864"); //MIDI (mid)
- }
- public static void main(String[] args) throws Exception
- {
- File f = new File("c://aaa.gif");
- if (f.exists())
- {
- String filetype1 = getImageFileType(f);
- System.out.println(filetype1);
- String filetype2 = getFileByFile(f);
- System.out.println(filetype2);
- }
- }
- /**
- * Created on 2010-7-1
- * <p>Discription:[getImageFileType,获取图片文件实际类型,若不是图片则返回null]</p>
- * @param File
- * @return fileType
- * @author:[shixing_11@sina.com]
- */
- public final static String getImageFileType(File f)
- {
- if (isImage(f))
- {
- try
- {
- ImageInputStream iis = ImageIO.createImageInputStream(f);
- Iterator<ImageReader> iter = ImageIO.getImageReaders(iis);
- if (!iter.hasNext())
- {
- return null;
- }
- ImageReader reader = iter.next();
- iis.close();
- return reader.getFormatName();
- }
- catch (IOException e)
- {
- return null;
- }
- catch (Exception e)
- {
- return null;
- }
- }
- return null;
- }
- /**
- * Created on 2010-7-1
- * <p>Discription:[getFileByFile,获取文件类型,包括图片,若格式不是已配置的,则返回null]</p>
- * @param file
- * @return fileType
- * @author:[shixing_11@sina.com]
- */
- public final static String getFileByFile(File file)
- {
- String filetype = null;
- byte[] b = new byte[50];
- try
- {
- InputStream is = new FileInputStream(file);
- is.read(b);
- filetype = getFileTypeByStream(b);
- is.close();
- }
- catch (FileNotFoundException e)
- {
- e.printStackTrace();
- }
- catch (IOException e)
- {
- e.printStackTrace();
- }
- return filetype;
- }
- /**
- * Created on 2010-7-1
- * <p>Discription:[getFileTypeByStream]</p>
- * @param b
- * @return fileType
- * @author:[shixing_11@sina.com]
- */
- public final static String getFileTypeByStream(byte[] b)
- {
- String filetypeHex = String.valueOf(getFileHexString(b));
- Iterator<Entry<String, String>> entryiterator = FILE_TYPE_MAP.entrySet().iterator();
- while (entryiterator.hasNext()) {
- Entry<String,String> entry = entryiterator.next();
- String fileTypeHexValue = entry.getValue();
- if (filetypeHex.toUpperCase().startsWith(fileTypeHexValue)) {
- return entry.getKey();
- }
- }
- return null;
- }
- /**
- * Created on 2010-7-2
- * <p>Discription:[isImage,判断文件是否为图片]</p>
- * @param file
- * @return true 是 | false 否
- * @author:[shixing_11@sina.com]
- */
- public static final boolean isImage(File file){
- boolean flag = false;
- try
- {
- BufferedImage bufreader = ImageIO.read(file);
- int width = bufreader.getWidth();
- int height = bufreader.getHeight();
- if(width==0 || height==0){
- flag = false;
- }else {
- flag = true;
- }
- }
- catch (IOException e)
- {
- flag = false;
- }catch (Exception e) {
- flag = false;
- }
- return flag;
- }
- /**
- * Created on 2010-7-1
- * <p>Discription:[getFileHexString]</p>
- * @param b
- * @return fileTypeHex
- * @author:[shixing_11@sina.com]
- */
- public final static String getFileHexString(byte[] b)
- {
- StringBuilder stringBuilder = new StringBuilder();
- if (b == null || b.length <= 0)
- {
- return null;
- }
- for (int i = 0; i < b.length; i++)
- {
- int v = b[i] & 0xFF;
- String hv = Integer.toHexString(v);
- if (hv.length() < 2)
- {
- stringBuilder.append(0);
- }
- stringBuilder.append(hv);
- }
- return stringBuilder.toString();
- }
- }
这样,不管是传入的文件有后缀名,还是无后缀名,或者修改了后缀名,真正获取到的才是该文件的实际类型,这样避免了一些想通过修改后缀名或者Content-type信息来攻击的因素。但是性能与安全永远是无法同时完美的,安全的同时付出了读取文件的代价。本人建议可采用后缀名与读取文件的方式结合校验,毕竟攻击是少数,后缀名的校验能排除大多数用户,在后缀名获取不到时再通过获取文件真实类型校验,这样来适当提高性能。
原文出处:
[1] shixing_11, Java判断文件类型 ,http://blog.csdn.net/shixing_11/article/details/5708145
Java判断文件类型的更多相关文章
- 用java流方式判断文件类型
这个方法只能在有限的范围内有效.并不是万金油 比如 图片类型判断,音频文件格式判断,视频文件格式判断等这种肯定是2进制且专业性很强的文件类型判断. 下面给出完整版代码 首先是文件类型枚取 packag ...
- java文件上传,自动判断文件类型
public enum FileType { /** * JEPG. */ JPEG("FFD8FF"), /** * PNG. */ PNG("89504E47&quo ...
- java判断文件真实类型
代码如下: import java.io.FileInputStream; import java.io.IOException; import java.util.HashMap; /** * &l ...
- 使用apache.tika判断文件类型
一. 判断文件类型一般可采用两种方式 1. 后缀名判断 简单易操作,但无法准确判断类型 2. 文件头信息判断 通常可以判断文件类型,但有些文件类型无法判断(如word和excel头信息的前几个字节是一 ...
- Python之基于十六进制判断文件类型
核心代码: #!/usr/bin/env python # -*- coding: utf-8 -*- # @Author : suk import struct from io import Byt ...
- JavaScript根据文件名判断文件类型
//JavaScript根据文件名判断文件类型 var imgExt = new Array(".png",".jpg",".jpeg",& ...
- 利用PHP取二进制文件头判断文件类型
<?php $files = array('D:\no.jpg', 'D:\no.png','D:\no2.JPEG','D:\no.BMP'); $fileTypes = array( 779 ...
- Linux中用st_mode判断文件类型
Linux中用st_mode判断文件类型 2012-12-11 12:41 14214人阅读 评论(4) 收藏 举报 分类: Linux(8) C/C++(20) 版权声明:本文为博主原创文章, ...
- php 读取文件头判断文件类型的实现代码
php代码实现读取文件头判断文件类型,支持图片.rar.exe等后缀. 例子: <?php $filename = "11.jpg"; //为图片的路径可以用d:/uploa ...
随机推荐
- ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2(转载)
ASP.NET Core 2.2 has been out for a while now and with it come some significant improvements to the ...
- jQuery.form 上传文件
今年大部分是都在完善产品,这几天遇到了一个问题,原来的flash组件不支持苹果浏览器,需要改.在网上搜了下,看到一个jQuery.form插件可以上传文件,并且兼容性很好,主要浏览器大部分都兼容,插件 ...
- windows 10 配置Java 环境变量(5步骤)
前提:1.windows 10 系统(不是win8,也不是win7)2.安装JDK步骤 1. 打开 环境变量窗口右键 This PC(此电脑) -> Properties(属性) -> A ...
- Java中关于位运算的面试题
位运算的效率是最高的,因为位位运算是直接对二进制进行操作 位运算只能应用于整型和char类型(char类型可以看做是特殊的无符号的整形) 面试题: a: 判断一个数是否是奇数 a & 1 == ...
- Centos7允许使用密码登录
现在使用云主机比较多,所以一般都是使用秘钥登录,当做一个集群的时候需要几台机器之间免密登录时,就需要修改他的配置文件了,刚做运维那会儿,很熟练,现在忘得差不多了,特此记录一下,下次又这个需求时就不 ...
- 分库分表的情况下生成全局唯一的ID
分库分表情况下 跨库的问题怎么解决? 分布式事务怎么解决? 查询结果集集合合并的问题? 全局唯一的id怎么解决? 一般要求:1.保证生成的ID全局唯一,不可重复 2.生成的后一个Id必须大于前一个Id ...
- LAMP架构性能测试+php优化
性能测试:1. 首先查看一下服务器的硬件性能free -m ---->查看一下内存的情况lscpu或者cat /proc/cpuinfo ------à查看一下cpu的情况2. ...
- DDL(数据库定义语言)(五)
一.数据定义语言(Data Definition Language)的基本操作 定义数据库.表等,包括CREATE语句.ALTER语句.DROP语句.CREATE语句用于创建数据库.数据表等,ALTE ...
- PAT 乙级 1048.数字加密 C++/Java
题目来源 本题要求实现一种数字加密方法.首先固定一个加密用正整数 A,对任一正整数 B,将其每 1 位数字与 A 的对应位置上的数字进行以下运算:对奇数位,对应位的数字相加后对 13 取余——这里用 ...
- Logstash连接Elasticsearch异常
1.背景 elasticsearch集群默认配置启动ok,logstash连接向里面发数据ok. 2.出现问题 修改elasticsearch.yml中的cluster.name,改为 esabc 然 ...