1.前言:

  1.1 在使用springMVC中,需要在过滤器中获取请求中的参数token,根据token判断请求是否合法;

  1.2 通过requst.getParameter(key)方法获得参数值;

    这种方法有缺陷:它只能获取  POST 提交方式中的Content-Type: application/x-www-form-urlencoded;

        HttpServletRequest request= (HttpServletRequest) req;
  String param = request.getParameter("param");

    

2.问题:

  在一般的请求中,content-type为:application/x-www-form-urlencoded;在此种请求中,使用request.getParam(key)方法可以获取到key对应的属性值;

  因为最近涉及到文件的上传操作,上传文件的请求中content-type为:multipart/form-data;此种请求无法直接用request.getParam(key)获取对应的属性值,request中获取的属性值全部为空,无法正常获取;

3.问题描述:

  3.1 在web.xml中配置的过滤器

  <filter>
<filter-name>requestFilter</filter-name>
<filter-class>util.web.RequestFilter</filter-class>
</filter> <filter-mapping>
<filter-name>requestFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

  

  3.2  过滤器RequestFilter.java中获取token做匹配

    在如下过滤器中,上传文件中的content-type:multipart/form-data使用获取request.getParameter(key)无法获取相应的值。需要借助Spring框架中的CommonsMultipartResolver.resolveMultipart(HttpServletRequest request)将request转为MultipartHttpServletRequest,从而使用getParameter(key)方法获取指定的值;

    * 在将对象转化完成后,要将转化完成的对象赋值给过滤链中的request参数中,即如下代码中的  req = multiReq; 赋值完成很重要,否则在controller层中依旧无法获取其他参数。

    如果不需要再filter中获取请求中的值,则无需如下的操作,在请求经过springMVC框架后,自动会识别请求方式,如果是文件请求,会自动调用CommonsMultipartResolver.resolveMultipart(HttpServletRequest request)方法转化;

package util.web;public class RequestFilter implements Filter {
protected FilterConfig filterConfig;
protected boolean filterEnabled;
protected int logLevel;
protected boolean needVCode;
protected List<String> noFilerList =null;
private CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
public RequestFilter() {
this.filterConfig = null;
this.filterEnabled = true;
this.logLevel = -1;
} @Override
public void destroy() {
// TODO Auto-generated method stub
} @Override
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
if(this.filterEnabled){
HttpServletRequest httpReq = (HttpServletRequest)req;
HttpServletResponse httpResp = (HttpServletResponse)resp;
String ctxPath = httpReq.getContextPath();
String requestUri = httpReq.getRequestURI(); //请求的全路径,比如:
String uri = requestUri.substring(ctxPath.length());//全路径除去ctxPath
String tarUri = uri.trim();
String operatorHtmlModel = (httpReq.getHeader("referer")!=null?httpReq.getHeader("referer"):"").trim(); //获取当前页面的url,判断url是否是后台而url(后台的html就两个)
//不在过滤列表里的url请求,过滤列表包括t_sys_filter表中数据及visitor角色用户下的授权页面
if(!this.isInNoFilerList(tarUri)){
UserInfo uInfo = SessionUtil.getCurrentUser();
LoginAccount regAccout=SessionUtil.getCurrentPlateLoginAccount();
int type = 0 ;//平台账号未登录
if(operatorHtmlModel.endsWith(Const.LOGIN_TYPE_HTML[0])||operatorHtmlModel.endsWith(Const.LOGIN_TYPE_HTML[1])){
type = 1;//后台账号未登录
}
// int type = (SessionUtil.getAttribute(Const.LOGIN_TYPE)!=null)?Integer.valueOf(SessionUtil.getAttribute(Const.LOGIN_TYPE).toString()):0;
if(regAccout==null){//平台账号未登录
if(tarUri.endsWith(".do")){
httpResp.sendRedirect(ctxPath+"/"+Const.TIMEOUT_SERVICE);
return;
}else if(tarUri.endsWith("/")){
httpResp.sendRedirect(ctxPath+"/"+Const.INDEX_PAGE);
return;
}
}else{//平台账号登录
if(tarUri.endsWith("/")){
httpResp.sendRedirect(ctxPath+"/error/noSecurity.htm");
return;
}else if(tarUri.endsWith(".do") && !isWithoutUri(tarUri)){
String contentType = httpReq.getContentType();//获取请求的content-type
String post_csrftoken = "";
if(contentType.contains("multipart/form-data")){//文件上传请求 *特殊请求
              /*
                
CommonsMultipartResolver 是spring框架中自带的类,使用multipartResolver.resolveMultipart(final HttpServletRequest request)方法可以将request转化为MultipartHttpServletRequest
                使用MultipartHttpServletRequest对象可以使用getParameter(key)获取对应属性的值
              */
                        MultipartHttpServletRequest multiReq = multipartResolver.resolveMultipart(httpReq);
post_csrftoken=multiReq.getParameter(Const.SESSION_CSRFTOKEN);//获取参数中的token
req = multiReq;//将转化后的reuqest赋值到过滤链中的参数 *重要
}else{//非文件上传请求
post_csrftoken=httpReq.getParameter(Const.SESSION_CSRFTOKEN);//获取参数中的token
}
//csrf防御:判断是否带token
//post_csrftoken=httpReq.getParameter(Const.SESSION_CSRFTOKEN);
String csrftoken=(String)SessionUtil.getAttribute(Const.SESSION_CSRFTOKEN);
if(post_csrftoken==null || !csrftoken.equals(post_csrftoken)){
//判断为不安全的访问
httpResp.sendRedirect(ctxPath+"/common/goNoSecurity.do");
return;
}
}
}
// 设定网页的到期时间,一旦过期则必须到服务器上重新调用
httpResp.setDateHeader("Expires", -1);
// Cache-Control 指定请求和响应应遵循的缓存机制 no-cache指示请求或响应消息是不能缓存的
httpResp.setHeader("Cache-Control", "no-cache");
// 用于设定禁止浏览器从本地缓存中调用页面内容,设定后一旦离开页面就无法从Cache中再调出
httpResp.setHeader("Pragma", "no-cache");
}
chain.doFilter(req, resp);
}
} @SuppressWarnings("unchecked")
@Override
public void init(FilterConfig cfg) throws ServletException {
//初始化操作
} private Boolean isWithoutUri(String tarUri){
String[] withoutUriStrings = {//无需匹配token的请求
"/common/goNoSecurity.do",
"/plateFormCommon/isLoginForPlateForm.do",
"/supplierForPlateForm/getCompanyListByRegId.do"
/*,"/PfTaskFileCtrl/addOrUpdateTaskImgFile1.do"*/
/*,"/PfTaskFileCtrl/addOrUpdateTaskImgFileForUpdate.do"*/
}; for(String uri:withoutUriStrings){
if(uri.equals(tarUri)){
return true;
}
}
return false;
} }

  3.3 控制层 PfTaskFileCtrl.java

  如果在filter中未将转化的request值赋值给过滤链,则在这里无法获取fileType对应的值;

package platform.common.controller;/**
* mogodb文件上传下载
* 项目名称:outsideeasy
* 类名称:PfTaskFileCtrl
* 创建人:mishengliang
* 创建时间:2016-4-26 下午1:55:19
* 修改人:mishengliang
* 修改时间:2016-4-26 下午1:55:19
* @version
*
*/
@Controller
@RequestMapping("PfTaskFileCtrl")
public class PfTaskFileCtrl { @Autowired
private PfRegisterAttchedService registerAttchedService;
@Autowired
private FileOptService fileService;
@Autowired
private PfUpdateRegisterAttchedService updateRegisterAttchedService;
@Autowired
private CompanyForPlateFormService companyForPlateFormService; @RequestMapping(value = { "/companyImageView" }, method = { RequestMethod.GET })
public ModelAndView gojsp_companyImageView(ModelAndView modelAndView ){
modelAndView.setViewName("/companyWindow/companyImageView");
return modelAndView;
} /**
* @Description:企业文件上传
* PfTaskFileCtrl
* addOrUpdateTaskImgFile1
* @param request
* @param response
* @return
* @throws Exception String
* @author yukai
* 2016-8-4 上午10:03:00
*/
@DocLogger(explain="企业文件上传")
@RequestMapping(value="addOrUpdateTaskImgFile1",method=RequestMethod.POST)
@ResponseBody
public String addOrUpdateTaskImgFile1(HttpServletRequest request,HttpServletResponse response) throws Exception{
Map<String,Object> qryParam = WebUtil.getDefaultParamsMap(request);
LoginAccount regAccount = SessionUtil.getCurrentPlateLoginAccount();
Map<String,Object> params=new HashMap<String, Object>();
JSONObject json = new JSONObject();
json.put("success", true);
/*
* 1.检查参数
*/
if(regAccount == null){//获取任务id
json.put("message", "未登录");
return json.toString() ;
}
     // *如果在filter中未将转化的request值赋值给过滤链,则在这里无法获取fileType对应的值
if(WebUtil.isEmpty(request.getParameter("fileType"))){//获取任务id
json.put("message", "没有文件类型值");
return json.toString() ;
}
/*
*2.赋值
*/
int fileType = Integer.parseInt(request.getParameter("fileType"));
String fileName = request.getParameter("fileName");
String formatType = request.getParameter("formatType"); PfRegisterAttched pfRegisterAttched = new PfRegisterAttched();
pfRegisterAttched.setFile_type_id(fileType);//文件类型值
pfRegisterAttched.setFile_name(fileName);//文件名 if(fileName.indexOf(",") != -1){
json.put("message", "文件名中存在非法字符(英文逗号),请先去除后上传");
return json.toString() ;
} /*
* 3.对文件信息的处理
*/
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
if(WebUtil.isEmpty((CommonsMultipartFile) multipartRequest.getFile("file"))){
json.put("message", "没有文件");
return json.toString() ;
}
CommonsMultipartFile file = (CommonsMultipartFile) multipartRequest.getFile("file"); //对应前台文件对象 if(file!=null && file.getSize()>0){//检查文件大小和格式
if (file.getSize() >5*1024*1024) {
json.put("message", "文件太大,超过5M");
return json.toString() ;
} String originalName=file.getOriginalFilename();
String this_suffix = "";
params.put(Const.ISIMG, 0);
params.put(Const.USE_TYPE, fileType);
params.put(Const.USERNAME, regAccount.getLogin_name());
params.put(Const.COM_ID, qryParam.get("companyId"));
params.put(Const.COM_NAME,companyForPlateFormService.getCompanyNameByCompanyId(qryParam));
boolean flag=false;//默认不 是图片
//获取文件后缀,与传过来的参数file_name重新组装文件名
if(originalName.indexOf(".")>0){//有后缀 XX.jpg XX.RAR
this_suffix=originalName.substring(originalName.lastIndexOf(".")); String[] format = null;
if("image".equals(formatType)){//判断上传文件的类型:image 图片,text 文档
format = Const.imgArray;
params.put(Const.ISIMG, 1);
}else if("text".equals(formatType)){
format = Const.otherArray;
} for(String suffix:format){
if(suffix.equalsIgnoreCase(this_suffix)){
flag=true;
break;
}
}
} if(!flag){
json.put("message", "不是指定格式");
return json.toString() ;
}else{
/*
* 4.进行信息的处理
*/
Date date = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String mongodbId=fileService.SaveFile(file,params);
pfRegisterAttched.setMogodb_id(mongodbId);//把存储mongoDb的文件序号存到数据库中
pfRegisterAttched.setCreate_dt(date);
pfRegisterAttched.setFile_format(this_suffix);
Integer id = registerAttchedService.addAppRegisterAttched(pfRegisterAttched);//获取存入信息的id
json.put("fileId",id);
json.put("mongodbId", mongodbId);
json.put("creatDate", sf.format(date));
json.put("message", "上传成功");
}
}else{
json.put("message", "文件不存在");
} return json.toString();
} }

4.解决方案

  在问题描述中已有问题解决方案。

  此方法主要利用了Spring框架中已有的工具类。

  参考资料:http://www.itdadao.com/articles/c15a279110p0.html

5.总结

  5.1 不同的content-type请求获取参数值的方法不同。

  5.2 在multipart/form-data请求方式中,需要利用SpringMVC框架中的CommonsMultipartResolver类包装转化为MultipartHttpServletRequest获取参数值;

6. 参考学习

  1. servlet3.0 Tomcat7.0 简洁方案

    如果使用的是servlet3.0及以上版本,multipart/form-data请求方式取值可以使用 HttpServletRequest.getPart(key)方法获取指定值;

    参考资料:http://stackoverflow.com/questions/2422468/how-to-upload-files-to-server-using-jsp-servlet/2424824#2424824

  2.通常的三种请求方式获取值方法

    * application/x-www-form-urlencoded

    *application/json

    * text/xml

  可以使用将请求转化为流,再转为字符串获取相应的值,通过如下方法获取的字符串获取指定的参数值;

  转化方法如下:

    /**
* 获取请求Body
*
* @param request
* @return
*/
public static String getBodyString(ServletRequest request) {
StringBuilder sb = new StringBuilder();
InputStream inputStream = null;
BufferedReader reader = null;
try {
inputStream = request.getInputStream();
reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
String line = "";
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return sb.toString();
}

  参考资料:http://blog.csdn.net/pyxly1314/article/details/51802652

    

web过滤器中获取请求的参数(content-type:multipart/form-data)的更多相关文章

  1. 在执行方法和Web资源中获取传递过来参数的值

    关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复228或者20161026可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong. ...

  2. 在过滤器中获取在web.xml配置的初始化参数

    在过滤器中获取在web.xml配置的初始化参数   例如 <filter> <filter-name>cross-origin</filter-name> < ...

  3. 4、处理方法中获取请求参数、请求头、Cookie及原生的servlet API等

    1.请求参数和请求头 使用@RequestParam绑定请求参数,在处理方法的入参处使用该注解可以把请求参数传递给请求方法 —— value :参数名 —— required : 是否必须,默认为tr ...

  4. AOP 环绕通知 (Schema-base方式) 和 AspectJ方式在通知中获取切点的参数

    环绕通知(Schema- base方式) 1.把前置通知和后置通知都写到一个通知中,组成了环绕通知 2.实现步骤: 2.1 新建一个类实现 MethodInterceptor 接口 public cl ...

  5. web项目中获取spring的bean对象

    Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架,如何在程序中不通过注解的形式(@Resource.@Autowired)获取Spring配置的bean呢? Bean工厂(c ...

  6. 从XMLHttpRequest中获取请求的URL

    在编写Ajax通用错误处理程序时,经常需要记录发生错误的XMLHttpRequest的请求URL.但查询文档,并未找到从XMLHttpRequest中获取请求URL的方法. 在javascript - ...

  7. 创建dynamics CRM client-side (十三) - 在HTML Web Resource中获取form elements & 获取外部js文件

    上一节我们讨论到创建HTML Web Resource. 但是纯HTML的页面不能满足我们的需求, 所以今天我们来做在HTML Web Resource中获取form elements Please ...

  8. org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'multipart/form-data;boundary=----WebKitFormBoundaryRAYPKeHKTYSNdzc1;charset=UTF-8' not supported

    原文:https://www.cnblogs.com/yueli/p/7552888.html 最近同事在做一个图片上传功能.在入参 body 中同时传入文件和其它基本信息结果出现如题异常.在此记录下 ...

  9. Web网页中动态数据区域的识别与抽取 Dynamical Data Regions Identification and Extraction in Web Pages

    Web网页中动态数据区域的识别与抽取 Dynamical Data Regions Identification and Extraction in Web Pages Web网页中动态数据区域的识别 ...

随机推荐

  1. Android RSA加密解密

    概述 RSA是目前最有影响力的公钥加密算法,该算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困 难,因此可以将乘积公开作为加密密钥,即公钥,而两个大素数 ...

  2. python3中urllib2的问题

    import urllib from urllib import request a = urllib.request.Request(url) b = urllib.request.urlopen( ...

  3. php array_udiff_uassoc比较数组的键值与值

    php array_udiff_uassoc 用于带索引检查计算数组的差集,用回调函数比较数据和索引.本文章通过实例向大家介绍array_udiff_uassoc函数的使用方法.需要的码农可以参考一下 ...

  4. 基于netty的心跳机制实现

    前言:在实现过程查找过许多资料,各种波折,最后综合多篇文章最终实现并上线使用.为了减少大家踩坑的时间,所以写了本文,希望有用.对于实现过程中有用的参考资料直接放上链接,可能有些内容相对冗余,不过时间允 ...

  5. 如何在C#中获得input文本框中的值

    前台 <input type="text" id="txt" name="txtn" style="width:213px& ...

  6. Ubuntu 安装BCM 43142无线网卡驱动

    ubuntu14.04 安装 bcm43142无线网卡 用命令lspci 查看无线网卡类型 然后下载对应的无线网卡驱动. 之后,使用下列命令安装,即可搜索无线热点了: sudo apt-get ins ...

  7. wex5 实战 二维码生成,扫描,蓝牙打印

    给人设计了一个小模块,要求是,把一个单号生成二维码,实现扫描查询单号具体信息,并能通过蓝牙把二维码打印出来.功能实现并不复杂,今天一口气把它搞定.来看效果. 一   效果演示: 二.二维码生成 1 在 ...

  8. PHPwind高级伪静态规则及方法

    phpwind iis下伪静态规则[ISAPI_Rewrite]RewriteRule ^(.*)/(.*)-htm-(.*)-(.*)\.html$ $1/$2\.php\?$3=$4Rewrite ...

  9. [转]使用xcode4 workspace 多个project协同工作

    转载地址:http://erlangprogram.com/use-xcode4-workspace   一般的某个应用单独新建一个 project 就可以了,然后把所有的程序文件都放在里面,这个可以 ...

  10. (转) CCEditBox 编辑框

    CCEditBox 编辑框 原文: http://blog.csdn.net/cloud95/article/details/8773470 分类: cocos2d-x 2013-04-08 19:1 ...