【转载:http://www.blogjava.net/bolo/archive/2012/05/01/376804.html】
大象根据研究与实际项目经验,向大家介绍一个关于文件类型验证的解决办法。不清楚的朋友可以了解下,知道的不喜勿喷。
对于文件上传,相信大家都不会陌生,我们都知道,文件在上传到服务器的过程中,都是以流的形式传输的,在后台处理文件上传的代码中,获得这个流,然后读取数据流将之保存到上传文件的临时目录中,如果有使用到MongoDB,再将这个文件存储到文件系统中。
大部分的文件上传都是通过HTML的上传组件完成的,而业务需求往往是有类型要求的,比如只允许上传jpg、gif、png类型的图片,或者是只允许上传Office文档等等,虽然可以用JavaScript对上传文件做一些类型验证之类的控制,但还是不能完全做到过虑。这时,就需要在后台,用代码来进一步完成这个验证工作。
到底通过什么方式可以做到正确验证呢?答案就是通过文件的头部信息,通过大量测试,大象发现每种类型的文件,他们最开始的一段信息都是一样的,比如Office97~03,它的头四位16进制信息就是d0 cf 11 e0,而Office2007则是50 4b 03 04,PDF为25 50 44 46,大家可以多用这样的文件分别测试一下,看看前四位16进制信息是不是都是一样的。当然这其中也有个别情况,比如jpg类型的图片,它的前四位16进制信息就有两种一个是ff d8 ff e0,另一个是ff d8 ff e1,区别是最后一位。知道了这些,我们就有一个方向了。
可能有同学有疑问了,为什么只取前四位,不是六位或八位呢?这是因为,大象根据反复测试发现,从第五位开始到第八位,同一种类型的文件,在这几位里面很有一些存在区别,像图片以及pdf,这种现象很多,为了避免同一类型的文件,因为这一些小的不同,要定义N多检测头信息,这样做似乎没有必要,因此大象才建议取前四位作为类型检测的依据。
不过说了这么多,还是没讲怎么做,这显然不是大象的风格,大象一般都从实际出发,用代码来说话。
package com.bolo.util;
public class FileValidateUtil {
public static boolean validateType(byte[] b, String customTypes) {
if (b != null) {
int size = b.length;
String hex = null;
StringBuilder contentType = new StringBuilder();
for (int i = 0; i < size; i++) {
hex = Integer.toHexString(b[i] & 0xFF);
if (hex.length() == 1) {
hex = "0" + hex;
}
contentType.append(hex);
if (i > 2)
break;
}
if (customTypes.indexOf(contentType.toString()) > -1) {
return Boolean.TRUE;
}
}
return Boolean.FALSE;
}
}
上面这段代码就是用来对文件类型作验证的方法,第一个参数是文件的字节数组,第二个就是定义的可通过类型。代码很简单,主要是注意中间的一处,将字节数组的前四位转换成16进制字符串,并且转换的时候,要先和0xFF做一次与运算。这是因为,整个文件流的字节数组中,有很多是负数,进行了与运算后,可以将前面的符号位都去掉,这样转换成的16进制字符串最多保留两位,如果是正数又小于10,那么转换后只有一位,需要在前面补0,这样做的目的是方便比较,取完前四位这个循环就可以终止了。
下面我们准备些文件来测试一下这段代码有没有问题。
package com.bolo.util;
import java.io.IOException;
import junit.framework.Assert;
import org.apache.commons.io.FileUtils;
import org.junit.Test;
import org.springframework.util.ResourceUtils;
import com.bolo.util.FileValidateUtil;
public class FileValidateUtilTest {
/**
* 文件头部信息,十六进制信息,取前4位
* 50 4b 03 04 office 2007+
* d0 cf 11 e0 office 97~03
* 25 50 44 46 pdf
* ff d8 ff e0 jpg,部分png与jpg头文件前4位一样
* ff d8 ff e1 jpg,一种不同的jpg头文件
* 89 50 4e 47 png
*/
private static final String FILE_TYPE = "504b0304 d0cf11e0 25504446 ffd8ffe0 ffd8ffe1 89504e47";
@Test
public void jpgTest(){
validateType("file/1.jpg");
}
@Test
public void docTest(){
validateType("file/2.doc");
}
@Test
public void docxTest(){
validateType("file/3.docx");
}
@Test
public void pdfTest(){
validateType("file/4.pdf");
}
@Test
public void exeTest(){
validateType("file/5.png");
}
private void validateType(String path){
try {
Assert.assertTrue(FileValidateUtil.validateType(FileUtils
.readFileToByteArray(ResourceUtils.getFile("classpath:" + path)), FILE_TYPE));
} catch (IOException e) {
e.printStackTrace();
}
}
}
从测试代码可以看到文件类型,只有第五个不是正确文件,是我将一个exe文件通过改后缀为png。这个测试类,用到了commons-io的FileUtils,需要在pom中加入这个依赖,而ResourceUtils在org.springframework.util包中,它属于spring-core.jar,大象这个测试类是放在之前ssm3工程test里面,要想正常运行测试,要在test/resources目录下建个file文件夹存放测试文件,最后编译之后file及其测试文件都会在test-classes下面,所以文件查找是以classpath:开头。
OK,运行测试,结果就是前四个成功,最后一个失败,这达到了我们的预期,只允许FILE_TYPE里面定义的文件类型通过测试。大家可以自己动手试验一下。
本文为菠萝大象原创,如要转载请注明出处。http://bolo.blogjava.net/
分享到:
相关推荐
(1)使用白名单控制上传文件类型,即只允许指定扩展名的文件上传。 (2)对上传文件后缀与MIME Type进行匹配校验, 对文件头信息与文件后缀进行匹配校验。 (3)对单个文件大小和总文件数进行限制, 避免拒绝服务...
通过以上步骤,Serv-U管理员能够有效地限制上传文件类型,从而提高服务器空间利用率并增强安全性。这种精细化管理策略不仅可以帮助组织避免存储资源的浪费,还能减少潜在的安全漏洞。同时,通过为不同部门提供定制化...
2. **优化文件类型验证**: - 可以使用正则表达式简化文件类型的判断逻辑。 - 示例:`var allowedExtensions = /(\.bmp|\.png|\.gif|\.jpg|\.jpeg)$/i;`,然后使用`allowedExtensions.test(ext)`来验证。 3. **...
因此,应该限制可接受的文件类型和大小,并在保存文件前进行验证和检查。 9. **性能优化**:对于大文件上传,应考虑分块上传、进度条显示、断点续传等功能,以提高用户体验。同时,确保服务器有足够的存储空间和...
### PHP上传文件大小限制的解决办法 在进行Web开发时,常常会遇到用户需要上传文件的需求。... #### 1.... **file_uploads=on** ...此外,考虑到安全性,还需对上传文件类型等进行验证,确保系统的稳定性和安全性。
在这个"struts2实现的文件上传(带文件类型和大小验证的)"示例中,我们将深入探讨如何在Struts2中实现这一功能。 首先,我们需要在Struts2的配置文件(struts.xml)中添加一个或多个action配置,用于处理文件上传...
### 文件类型验证 `VerifyFileType.java` 类很可能包含了一个方法来识别文件的实际类型,这通常通过读取文件的二进制头部信息来实现。在Java中,没有内置的方式来直接确定文件类型,但可以通过以下策略实现: 1. *...
建议实施额外的安全措施,比如文件类型过滤、上传前的文件检查等。 - **监控与日志**:定期检查服务器的日志文件可以帮助发现潜在问题,及时调整配置或采取相应措施。 通过以上步骤和注意事项,可以有效地解决...
在Struts2中,为了防止恶意用户上传不安全的文件(如脚本或可执行文件),系统会设定允许上传的文件类型。当上传的文件类型不在这些允许的类型列表中时,就会出现此类错误。这个问题通常可以通过调整Struts2的配置...
以上内容涵盖了如何使用JavaScript验证上传文件类型的基本方法,包括获取文件名、截取文件扩展名、字符串匹配验证等操作,以及对前端文件类型验证安全性的简要说明和对其他JavaScript知识专题的介绍。掌握这些内容...
"上传文件jsweb前端(包含文件格式限制)"这个项目旨在提供一个完整的前端文件上传解决方案,它不仅支持基本的文件上传操作,还包含了对文件格式和大小的严格限制,以确保用户上传的数据符合预设的标准,类似于163...
3. **用户体验**:合理设置上传文件的大小限制和类型,避免用户等待时间过长,同时提供清晰的上传状态反馈。 总结,jQuery文件批量上传控件以其简洁的API、丰富的功能和良好的用户体验,成为Web开发中实现文件上传...
常见的安全措施包括检查文件类型、大小,甚至进行内容检测。此外,上传的文件应存储在受保护的目录下,避免直接暴露在Web根目录,以防止被直接访问。 文件上传的性能优化也是一个重要话题。为了提高上传速度和减少...
因此,服务器管理员需要采取一些安全措施来防止这种攻击,例如使用白名单验证、限制上传文件类型、使用防火墙等。 本课程主要讲解了文件上传绕过黑名单验证的原理和方法,包括双写绕过原理、基于黑名单验证代码分析...
8. **安全考虑**:虽然Flash的多文件上传提供了便利,但同时也增加了安全风险,如跨站请求伪造(CSRF)和文件类型攻击。因此,服务器端需要对上传的文件进行验证和过滤,防止恶意文件的上传。 9. **源码分析**:`...
在实际应用中,我们还需要处理更多细节,例如验证文件类型、大小限制、错误处理等。你可以通过设置Gin中间件或者在处理器内部进行这些操作。例如,检查文件大小可以使用`c.Request.MultipartForm.File["file"][0]....
为了上传文件,我们需要先在项目中引入阿里云的OSS SDK,然后创建OSSClient实例,调用其`putObject`方法进行上传。以下是一个基础的OSS普通上传示例: ```java import com.aliyun.oss.OSS; import ...
5. **安全性**:可能实现了验证机制,如检查文件类型、大小限制,防止恶意文件上传。 6. **日志记录**:记录上传过程,便于调试和监控。 文件名称列表中的"CommHandler"可能是指这个通用HttpHandler的实现文件或者...
- **安全措施**:验证文件类型、大小,避免恶意文件上传,可以通过`getimagesize()`或`finfo_file()`检查文件类型,限制上传大小防止DoS攻击。 - **文件重命名**:通常建议重命名上传的文件,以防止文件名冲突或...
这三个库的结合使用,使得开发人员能够轻松地构建一个功能完备的文件上传系统,包括验证文件类型、大小,处理多文件上传,以及有效地存储和管理上传的文件。在实际开发中,这些库经常与Servlet、Spring MVC等Web框架...