上传文件如果不做好安全控制的话,攻击者很有可能上传一些恶意攻击脚本,然后再执行,达到不可告人的目的。于是我们需要判断文件的类型,通常情况下我们只是判断了文件的后缀名,根据文件的后缀名的白名单和黑名单来过滤。这种方式非常不可靠,因为后缀名完全可以伪造。例如exe的伪造成jpg。
通过文件内容的判断文件的类型是目前最可靠的,因为一般根据文件的开头一些字节的特征就能判断这个文件的类型,而不需要读取整个文件,所以可行性也比较高。下面给出一个例子。
首先定义文件类型的识别数据FileType.java
public enum FileType {
/**
* JEPG.
*/
JPEG("FFD8FF"),
/**
* PNG.
*/
PNG("89504E47"),
/**
* GIF.
*/
GIF("47494638"),
/**
* TIFF.
*/
TIFF("49492A00"),
/**
* RTF.
*/
RTF("7B5C727466"),
/**
* DOC
*/
DOC("D0CF11E0"),
/**
* XLS
*/
XLS("D0CF11E0"),
/**
* ACCESS
*/
MDB("5374616E64617264204A"),
/**
* Windows Bitmap.
*/
BMP("424D"),
/**
* CAD.
*/
DWG("41433130"),
/**
* Adobe Photoshop.
*/
PSD("38425053"),
/**
* XML.
*/
XML("3C3F786D6C"),
/**
* HTML.
*/
HTML("68746D6C3E"),
/**
* Adobe Acrobat.
*/
PDF("255044462D312E"),
/**
* ZIP Archive.
*/
ZIP("504B0304"),
/**
* RAR Archive.
*/
RAR("52617221"),
/**
* Wave.
*/
WAV("57415645"),
/**
* AVI.
*/
AVI("41564920");
private String value = "";
/**
* Constructor.
*
* @param type
*/
private FileType(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
然后读取文件的前面几个字节转化成十六进制
public final class FileTypeJudge {
/**
* 二进制转化为16进制
*/
private static String bytes2hex(byte[] bytes) {
StringBuilder hex = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
String temp = Integer.toHexString(bytes[i] & 0xFF);
if (temp.length() == 1) {
hex.append("0");
}
hex.append(temp.toLowerCase());
}
return hex.toString();
}
/**
* 读取文件头
*/
private static String getFileHeader(String filePath) throws IOException {
byte[] b = new byte[28];//这里需要注意的是,每个文件的magic word的长度都不相同,因此需要使用startwith
InputStream inputStream = null;
inputStream = new FileInputStream(filePath);
inputStream.read(b, 0, 28);
inputStream.close();
return bytes2hex(b);
}
/**
* 判断文件类型
*/
public static FileType getType(String filePath) throws IOException {
String fileHead = getFileHeader(filePath);
if (fileHead == null || fileHead.length() == 0) {
return null;
}
fileHead = fileHead.toUpperCase();
FileType[] fileTypes = FileType.values();
for (FileType type : fileTypes) {
if (fileHead.startsWith(type.getValue())) {
return type;
}
}
return null;
}
public static void main(String[] args) throws Exception{
System.out.println(FileTypeJudge.getType("D:\\Download\\doc.rar"));
}
}
参考链接:http://www.cnblogs.com/mq0036/p/3912355.html