SpringBoot后端上传文件类型检测方式

目录
  • 本文通过文件流头部判断文件类型
  • 1、添加配置文件checkFileHeader.properties
  • 2、编写读取properties文件类
  • 3、编写拦截器
  • 4、配置拦截文件

文件上传大部分通过web前端判断后尾名或者service后端判断后尾名,这种操作具有一定的风险,比如:我可以将一个jsp页面,修改后尾名改成jpg文件进行上传,由于图片预览功能,这个文件会被执行,这时就可以发送用户数据到指定的服务下,窃取用户信息。

本文通过文件流头部判断文件类型

不同的文件具有不同的头部,比如:

不同的文件具有不同的头部信息,以SpringBoot为例,通过拦截器拦截文件流进行判断:

1、添加配置文件checkFileHeader.properties

在src/main/resources中增加配置文件checkFileHeader.properties,文件内容:

JPEG=FFD8FF
PNG=89504E47
GIF=47494638
TXT=75736167
PDF=255044462D312E
DOC=D0CF11E0
XML=3C3F786D6C
DOCX=504B0304
APK=504B030414000808
IPA=504B03040A000000

2、编写读取properties文件类

读取checkFileHeader.properties文件内容,用于拦截器判断

/**
 * 读取文件流头信息
 * @author hanjie
 *
 */
public class FileHeaderHelper {    
    private static FileHeaderHelper me ;
    private static List<String> headerList ; 
    private FileHeaderHelper(){}    
    public static FileHeaderHelper getInstance(){
        if(me == null){
            me = new FileHeaderHelper() ;
        }
        return me ;
    }
    
    public List<String> getHeaderList(){
        if(headerList == null){
            headerList = new ArrayList<String>() ;
            
            PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
            String classpathResource = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + "/fileheader.properties";
            Properties p = new Properties();
            try {
                Resource[] res = resolver.getResources(classpathResource) ;
                for (Resource re : res) {
                    p.load(re.getInputStream());
                    break ;
                }
                
            } catch (IOException e) {
                e.printStackTrace();
            }
            for (Map.Entry<Object, Object> item : p.entrySet()) {
                headerList.add(item.getValue().toString()) ;
            }
        }        
        return headerList ;
    }
}

3、编写拦截器

拦截去中,获取文件流,读取文件流前8个字节,根据需要可以读取更多字节判读,8个字节转成16进制为16个字符串,我这里最长的APK/IPA文件也就16个字节,所以读取8个字节,读取字节后判断是否checkFileHeader.properties文件中字符串

/**
 * 文件上传拦截器
 * @author hanjie
 *
 */
public class FileHeaderCheckInterceptor implements HandlerInterceptor {
 
    @Override
    public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception {
        // 判断是否为文件上传请求
        if (request != null && request instanceof MultipartHttpServletRequest) {
            MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
            Map<String, MultipartFile> files = multipartRequest.getFileMap();
            Iterator<String> iterator = files.keySet().iterator();
            while (iterator.hasNext()) {
                String formKey = (String) iterator.next();
                MultipartFile multipartFile = multipartRequest.getFile(formKey);
                //String filename = multipartFile.getOriginalFilename();
                byte[] file = multipartFile.getBytes() ;
                
                获取字节流前8字节,差不多够了,不行再加
                int HEADER_LENGTH = 8 ;
                
                if(file.length>HEADER_LENGTH){
                    //转成16进制
                    StringBuilder sb = new StringBuilder();
                    for(int i=0;i<HEADER_LENGTH;i++){
                        int v = file[i] & 0xFF;     
                        String hv = Integer.toHexString(v);     
                        if (hv.length() < 2) {     
                            sb.append(0);     
                        }     
                        sb.append(hv);
                    }                    
                    
                    boolean isFound = false ;
                    String fileHead = sb.toString().toUpperCase() ;
                    List<String> headerList = FileHeaderHelper.getInstance().getHeaderList() ;
                    for(String header : headerList){
                        if(fileHead.startsWith(header)){
                            isFound = true ;
                            break ;
                        }
                    }
                    if(!isFound){
//                        throw new BaseRunException("上传文件有异常,已被系统禁止!") ;
                        System.out.println("----------上传文件有异常,已被系统禁止!头部信息:"+fileHead);
                        response.setCharacterEncoding("UTF-8");
                        response.setContentType("application/json;charset=utf-8"); 
                        PrintWriter printWriter = response.getWriter();    
                        printWriter.write("上传文件有异常,已被系统禁止!");    
                        return false; 
                    }
                }
            }
        }
        return true;
    }
 
    @Override
    public void postHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        // TODO Auto-generated method stub 
    }
 
    @Override
    public void afterCompletion(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        // TODO Auto-generated method stub 
    }    
}

4、配置拦截文件

拦截器写完了,配置下让它生效,在Configuration中配置拦截器,拦截文件流进行判断

@Configuration
public class MyfWebAppConfiguration extends WebMvcConfigurerAdapter {
    
    //拦截器,拦截文件流
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new FileHeaderCheckInterceptor()) 
                .addPathPatterns("/**"); 
    }
    
//    //注册过滤
//    @Bean
//    public FilterRegistrationBean myFilterRegistration() {
//     
//       FilterRegistrationBean registration = new FilterRegistrationBean();
//       registration.setFilter(new LoginFilter());
//       registration.addUrlPatterns("/serviceInvoke");
//       //registration.addInitParameter("paramName", "paramValue");
//       registration.setName("loginFilter");
//       registration.setOrder(1);
//       return registration;
//     }
//    
//    
//    //注册servlet
//    @Bean  
//    public ServletRegistrationBean myServletRegistration() {  
//        ServletRegistrationBean registration = new ServletRegistrationBean(new DownloadServlet());  
//        registration.addUrlMappings("/download");  
//        return registration;  
//    } 
}

页面消息提醒已经在printWriter中输出了,根据自己的页面编写显示吧。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • SpringBoot文件上传控制及Java 获取和判断文件头信息

    之前在使用SpringBoot进行文件上传时,遇到了很多问题.于是在翻阅了很多的博文之后,总算将上传功能进行了相应的完善,便在这里记录下来,供自己以后查阅. 首先,是建立一个标准的SpringBoot 的工程,这里使用的IDE是Intellij Idea,为了方便配置,将默认的配置文件替换为了application.yml. 1.在index.html中进行文件上传功能,这里使用的文件上传方式是ajax,当然也可以按照自己的具体要求使用传统的表单文件上传. <!DOCTYPE html> &l

  • springboot实现文件上传步骤解析

    这篇文章主要介绍了springboot实现文件上传步骤解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 第一步编写上传的前段页面 <div> <button type="button" class="btn btn-primary" ng-click="openAddModal()" data-toggle="modal" data-target=&quo

  • Springboot文件上传功能简单测试

    在static文件夹中创html页面 内容为: <html> <head></head> <body> <form action="/fileuploadContorller" method="post" enctype="multipart/form-data"> <input type="file" name="file"/> &l

  • SpringBoot后端上传文件类型检测方式

    目录 本文通过文件流头部判断文件类型 1.添加配置文件checkFileHeader.properties 2.编写读取properties文件类 3.编写拦截器 4.配置拦截文件 文件上传大部分通过web前端判断后尾名或者service后端判断后尾名,这种操作具有一定的风险,比如:我可以将一个jsp页面,修改后尾名改成jpg文件进行上传,由于图片预览功能,这个文件会被执行,这时就可以发送用户数据到指定的服务下,窃取用户信息. 本文通过文件流头部判断文件类型 不同的文件具有不同的头部,比如: 不

  • java实现上传文件类型检测过程解析

    这篇文章主要介绍了java实现上传文件类型检测过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 在进行文件上传时,特别是向普通用户开放文件上传功能时,需要对上传文件的格式进行控制,以防止黑客将病毒脚本上传.单纯的将文件名的类型进行截取的方式非常容易遭到破解,上传者只需要将病毒改换文件名便可以完成上传. 可以读取文件的十六进制的文件头,来判断文件真正的格式. 读取文件的二进制数据并将其转换为十六进制时,同类型文件的文件头数据是相同的,即使改

  • PHP判断上传文件类型的解决办法

    分享给大家php判断上传文件类型的方法,大家一起学习学习. /** * 读取文件前几个字节 判断文件类型 * @return String */ function checkTitle($filename){ $file=fopen($filename, "rb"); $bin=fread($file, 2); //只读2字节 fclose($file); $strInfo =@unpack("c2chars", $bin); $typeCode=intval($s

  • JS简单验证上传文件类型的方法

    本文实例讲述了JS简单验证上传文件类型的方法.分享给大家供大家参考,具体如下: function checkType(){ //得到上传文件的值 var fileName=document.getElementById("file_logo").value; //返回String对象中子字符串最后出现的位置. var seat=fileName.lastIndexOf("."); //返回位于String对象中指定位置的子字符串并转换为小写. var extensi

  • php限制上传文件类型并保存上传文件的方法

    本文实例讲述了php限制上传文件类型并保存上传文件的方法.分享给大家供大家参考.具体如下: 下面的代码演示了php中如何获取用户上传的文件,并限制文件类型的一般图片文件,最后保存到服务器 <?php $allowedExts = array("gif", "jpeg", "jpg", "png"); $extension = end(explode(".", $_FILES["file&qu

  • JS控制FileUpload的上传文件类型实例代码

    JS代码如下: function CheckFile(obj) { var array = new Array('gif', 'jpeg', 'png', 'jpg'); //可以上传的文件类型 if (obj.value == '') { alert("让选择要上传的图片!"); return false; } else { var fileContentType = obj.value.match(/^(.*)(\.)(.{1,8})$/)[3]; //这个文件类型正则很有用:)

  • 解决springboot项目上传文件出现临时文件目录为空的问题

    最近写文件上传到服务器读取的代码,前端使用FormData上传,服务端用MultipartFile接收,自己测试了下MultipartFile对象有什么东西,结果一般属性都能出来,测试getInputStrea()方法的时候出现了以下错误,简单一看这是什么目录,从来没见过啊: 百度一番之后发现了这是临时文件存放的路径,不清楚根据什么去放在这个目录的,但是这个目录本机的确没有,linux系统下好像系统会10天清空一次,翻阅了API底下有这个 百度的时候也发现另外一个坑,spring配置的MaxIn

  • SpringBoot实现上传文件到AWS S3的代码

    简单记录一下在Springboot中上传文件到AWS S3存储服务的代码. 在 application.xml中添加aws相关配置: custom:   aws:     access-key: CHOBITACCESSKEY     secret-key: CHOBIT/THISIS006SECRET007Key/dotORG     bucket: zhyea     endpoint: www.zhyea.com:80 新建一个 AwsS3Componment类来执行上传文件操作: @Co

  • ASP.net判断上传文件类型的三种有效方法

    一.安全性比较低,把文本文件1.txt改成1.jpg照样可以上传,但其实现方法容易理解,实现也简单,所以网上很多还是采取这种方法. 复制代码 代码如下: Boolean fileOk = false; string path = Server.MapPath("~/images/"); //判断是否已经选取文件 if (FileUpload1.HasFile) { //取得文件的扩展名,并转换成小写 string fileExtension = System.IO.Path.GetEx

  • JavaScript判断FileUpload控件上传文件类型

    为了代码变得更加简捷,笔者使用了正则表达式来获取文件扩展名,如果读者对正则表达式不太了解或者从来没有接触过,请马上恶补一下吧!毕竟它非常重要,大多数的编程语言都支持正则表达式. 大家都知道,后台获取FileUpload扩展名方法: string ext = Path.GetExtension(fu.PostedFile.FileName); JS判断FileUpload控件上传文件的扩展名: <html xmlns="http://www.w3.org/1999/xhtml"&g

随机推荐