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

网友投稿 673 2022-08-18


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

目录本文通过文件流头部判断文件类型1、添加配置文件checkFileHeader.properties2、编写读取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 headerList ;

private FileHeaderHelper(){}

public static FileHeaderHelper getInstance(){

if(me == null){

me = new FileHeaderHelper() ;

}

return me ;

}

public List getHeaderList(){

if(headerList == null){

headerList = new ArrayList() ;

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 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 files = multipartRequest.getFileMap();

Iterator 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

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 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中输出了,根据自己的页面编写显示吧。

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 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中输出了,根据自己的页面编写显示吧。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:springboot+mybatis+枚举处理器的实现
下一篇:SpringBoot 枚举类型的自动转换的实现
相关文章

 发表评论

暂时没有评论,来抢沙发吧~