SpringMVC全局文件上传类型限制【终极解决方案】

各位小伙伴们,有没有遇到这种情况,在信息安全日益受到各方重视的当下,白帽子越来越多,相应的作为开发人员的安全意识也得与日俱增。但是呢,总会有各种各种的原因,会出现全局性系统性的问题,你无法解决,或者无从下手。怎么办?没办法,只有回归本质。

今天分享一个SpringMVC全局文件上传类型限制终极解决方案,为那些还在迷茫该如何处理全局性文件上传漏洞的小伙伴送来一份小礼物。在阅读我的代码之前,请看下面的一篇关于SpringMVC文件上传的博文摘要。博文地址http://exceptioneye.iteye.com/blog/1314958

    客户端浏览器将按照 RFC 1867 所规定的格式,对提交表单内容进行编码,服务器端只需要根据 RFC 1867 规定的格式对请求中的信息进行解码,就可以获得客户端表单提交的数据,包括上传的文件。 

        既然 RFC 1867 所规定的规则是一定的,所以,我们没有必要每次都根据这一规则分析每一次请求中的信息。既然是通用的逻辑,当然也就有通用的类库,比如早期的 jsp smart upload 和 Oreilly 的 COS 类库,以及现在使用最多的 Commons FileUpload 类库。实际开发中,我们只需要使用这些专门针对表单的文件上传处理类库即可。 

        在实际基于表单的文件上传功能的时候,Spring MVC 框架底层实际上也是使用了以上几种类库。只不过,通过 org.springframework.web.multipart.MultipartResolver 接口的抽象,Spring MVC 将具体选用哪一种类库的权利留给了我们。 

        MultipartResolver 位于 HandlerMapping 之前,请求一来就交由它来处理。当 Web 请求到达 DispatcherServlet 并等待处理的时候,DispatcherServlet 首先会检查能否从自的 WebApplicationContext 中找到一个名称为 multipartResolver(由 DispatcherServlet 的常量 MULTIPART_RESOLVER_BEAN_NAME 所决定)的 MultipartResolver 实例。如果能够获得一个 MultipartResolver 的实例,DispatcherServlet 将调用 MultipartResolver 的 isMultipart(request) 方法检查当前 Web 请求是否为 multipart类型。如果是,DispatcherServlet 将调用 MultipartResolver 的 resolveMultipart(request) 方法,对原始 request 进行装饰,并返回一个 MultipartHttpServletRequest 供后继处理流程使用(最初的 HttpServletRequest 被偷梁换柱成了 MultipartHttpServletRequest),否则,直接返回最初的 HttpServletRequest。来看看 UML 类图: 

MultipartRequest 毕竟是接口,接口就是接口,总得有人实现。AbstractMultipartHttpServletRequest 这个抽象类持有 MultiValueMap<String, MultipartFile> multipartFiles 这样一个实例变量,有了这个 map,把 MultipartRequest 接口里的方法逐一实现就不是难事了。现在的问题是,multipartFiles 从哪来的?不可能像孙悟空似的从石缝里蹦出来吧。。。。。 

        再回到 MultipartResolver。MultipartResolver 的 isMultipart(request) 方法好实现,当判断出当前的 request 是 multipart 类型的请求,它将调用 MultipartResolve 的 resolveMultipart(request)。这里的 request 就是原始的 HttpServletRequest 对象,奇迹就出现在这里。以 CommonsMultipartResolver 为例,当调用 resolveMultipart(request) 时,看看它是如何创建 MultipartRequest 的:
  1. public MultipartHttpServletRequest resolveMultipart(final HttpServletRequest request) throws MultipartException {
  2. Assert.notNull(request, "Request must not be null");
  3. if (this.resolveLazily) {
  4. return new DefaultMultipartHttpServletRequest(request) {
  5. @Override
  6. protected void initializeMultipart() {
  7. MultipartParsingResult parsingResult = parseRequest(request);
  8. setMultipartFiles(parsingResult.getMultipartFiles());
  9. setMultipartParameters(parsingResult.getMultipartParameters());
  10. }
  11. };
  12. }
  13. else {
  14. MultipartParsingResult parsingResult = parseRequest(request);
  15. return new DefaultMultipartHttpServletRequest(
  16. request, parsingResult.getMultipartFiles(), parsingResult.getMultipartParameters());
  17. }
  18. }

OK。其余的内容请移步至对应的文章。

想要全局实现文件上传限制,首先你可能想到的有两种。没错,那就是过滤器和拦截器。但是呢,过滤器玩了半天也

没有实现预期结果,因此拦截方法采用拦截器来实现。

废话不说  直接上代码

SpringMVC拦截器配置:

注意:如果你的文件上传请求比较特殊的话,尽量压缩拦截范围,否则可能影响用户体验。

  <mvc:interceptor>
        <mvc:mapping path="/public/mypath/**/*" />
        <bean class="x.x.FileShellInterceptor"></bean>
  </mvc:interceptor>

SpringMVC请求拦截器:

public class FileShellInterceptor extends HandlerInterceptorAdapter{

	@Override
	public boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler) throws Exception {
		HttpServletRequest req=(HttpServletRequest)request;
		MultipartResolver res=new org.springframework.web.multipart.commons.CommonsMultipartResolver();
		if(res.isMultipart(req)){
//			System.out.println("我是文件上传请求");
			MultipartHttpServletRequest  multipartRequest=(MultipartHttpServletRequest) req;
			Map<String, MultipartFile> files= multipartRequest.getFileMap();
			Iterator<String> iterator = files.keySet().iterator();
			while (iterator.hasNext()) {
				String formKey = (String) iterator.next();
//				System.out.println("表单key:"+formKey);
				MultipartFile multipartFile = multipartRequest.getFile(formKey);
				if (!ValidateUtils.isEmpty(multipartFile.getOriginalFilename())) {
					String filename = FileUtils.getDateFileName(multipartFile.getOriginalFilename());
//					System.out.println("我是文件"+multipartFile.getOriginalFilename());
					if(checkFile(filename)){
						return true;
					}else{
						request.getSession().removeAttribute(Global.SESSION_ADMIN_USERNAME);
						HttpUtils.setActionMessage(request, "尊敬的管理员,您的登录信息已经过期,请重新登录!",ACTION_MSG_TYPE.ERROR ,true);
						String redirectURL=request.getContextPath()+"/admin/login.jspx";
						//解决登录页面 显示在frame中的问题。
						HttpUtils.write2Client(response, "<html><head><script>top.location.href='"+redirectURL+"'</script></head></html>");
						return false;
					}
				}
			}
			return true;
		}else{
			return true;
		}
	}
	private  boolean checkFile(String fileName){
		boolean flag=false;
		String suffixList="xls,xlsx,jpg,gif,png,ico,bmp,jpeg";
		//获取文件后缀
		String suffix=fileName.substring(fileName.lastIndexOf(".")+1, fileName.length());

		if(suffixList.contains(suffix.trim().toLowerCase())){
			flag=true;
		}
		return flag;
	}
}

好啦。周五了,咱们都可以安心地回家过周末了。

原文地址:http://blog.csdn.net/zgs_shmily/article/details/45917527

原文地址:http://blog.csdn.net/zgs_shmily/article/details/45917527

时间: 2024-10-03 22:37:59

SpringMVC全局文件上传类型限制【终极解决方案】的相关文章

SpringMVC中文件上传的客户端验证

SpringMVC中文件上传的客户端验证 客户端验证主要思想:在jsp页面中利用javascript进行对文件的判断,完成验证后允许上传 验证步骤:1.文件名称 2.获取文件的后缀名称 3.判断哪些文件类型允许上传 4.判断文件大小 5.满足条件后跳转后台实现上传 前台界面(验证上传文件是否格式满足要求): <body> <h2>文件上传</h2> <form action="upload01" method="post" 

SpringMVC单文件上传

最近在看SpringMVC的文件上传部分,其实大多数系统都要涉及到文件上传,以前对于Struts的文件上传功能也做过总结了,今天主要说明一下如何使用SpringMVC进行表单上的文件上传以及多个文件同时上传的步骤. 一.设置配置文件: SpringMVC 用的是 的MultipartFile来进行文件上传 所以我们首先要配置MultipartResolver:用于处理表单中的file [html] view plaincopyprint? <!-- 配置MultipartResolver 用于文

Spring Framework源码(十):SpringMVC之文件上传

我们这一章讲SpringMVC中文件上传的应用,首先我们还是从DispatcherServlet这个核心分发器开始讲起: processedRequest = checkMultipart(request); 还记得上一章讲doDispatch这个方法时见过的方法吧?现在我们来分析下这个方法的具体解析过程: protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartExcepti

SpringMVC学习--文件上传

简介 文件上传是web开发中常见的需求之一,springMVC将文件上传进行了集成,可以方便快捷的进行开发. springmvc中对多部件类型解析 在 页面form中提交enctype="multipart/form-data"的数据时,需要springmvc对multipart类型的数据进行解析.在springmvc.xml中配置multipart类型解析器. 1 <!-- 文件上传 --> 2 <bean id="multipartResolver&qu

Extjs4 + springMVC的文件上传

用springMVC来做项目,如果遇到文件上传,那么一定要用spring自带的文件处理类来处理上传的文件,因为效率实在高过其他的. 从界面传过来的参数,如果设置了值对象,那么可以从值对象里面取出字符串类型的普通参数,如果不这样做,也可以直接从request里面获得,两种方法都可以. 问题是如果值对象里面写了其他类型的变量,妄想像Struts2那样处理,springMVC就会报出400 Bad Request的错误. 在Struts2里面,我们可以定义一个值对象为 public class Ima

一起学SpringMVC之文件上传

概述 在Web系统开发过程中,文件上传是普遍的功能,本文主要以一个简单的小例子,讲解SpringMVC中文件上传的使用方法,仅供学习分享使用,如有不足之处,还请指正. 文件上传依赖包 如下所示,文件上传依赖的jar包主要有两个: commons-fileupload-1.4.jar commons-io-2.6.jar SpringMVC支持文件上传操作步骤 1. 配置支持文件上传的Bean 如下所示:主要配置默认的编码方式,和上传文件的限制大小 1 <!-- 文件上传支持 --> 2 <

关于SpringMVC的文件上传

关于文件的上传,之前写过2篇文章,基于Struts2框架,下面给出文章链接: <关于Struts2的文件上传>:http://www.cnblogs.com/lichenwei/p/3927964.html <关于Struts2的多文件上传>:http://www.cnblogs.com/lichenwei/p/3928200.html 其实文件上传的原理都是一样的,基于SpringMVC的文件上传实现要比Struts2要来得简单许多. 好了,废话不多说,直接切入主题吧,关于上传原

SpringMVC经典系列-12基于SpringMVC的文件上传---【LinusZhu】

注意:此文章是个人原创,希望有转载需要的朋友们标明文章出处,如果各位朋友们觉得写的还好,就给个赞哈,你的鼓励是我创作的最大动力,LinusZhu在此表示十分感谢,当然文章中如有纰漏,请联系[email protected],敬请朋友们斧正,谢谢. 不知不觉已经把Spring的基础部分讲解完了,所讲述的都是在项目中经常用到的东西,是经得住考验的,接下来的部分主要是要讲述使用SpringMVC进行的文件上传.处理Ajax请求.自定义拦截器功能的实现,不多说了,首先讲解文件上传部分,开始--     

JavaScript如何判断文件上传类型 实例分享

分享下JavaScript判断文件上传类型的方法,可针对重复的内容触发onchange事件. JavaScript判断文件上传类型的方法:文件上传时用到一个功能,使用html元素的input标签实现: <input id="imageFile" name="imageFile1" accept="image/jpg,image/jpeg,image/png,image/bmp,image/gif" type="file"