web过滤器中获取请求的参数(content-type:multipart/form-data)
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)方法获取指定值;
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)的更多相关文章
- 在执行方法和Web资源中获取传递过来参数的值
关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复228或者20161026可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong. ...
- 在过滤器中获取在web.xml配置的初始化参数
在过滤器中获取在web.xml配置的初始化参数 例如 <filter> <filter-name>cross-origin</filter-name> < ...
- 4、处理方法中获取请求参数、请求头、Cookie及原生的servlet API等
1.请求参数和请求头 使用@RequestParam绑定请求参数,在处理方法的入参处使用该注解可以把请求参数传递给请求方法 —— value :参数名 —— required : 是否必须,默认为tr ...
- AOP 环绕通知 (Schema-base方式) 和 AspectJ方式在通知中获取切点的参数
环绕通知(Schema- base方式) 1.把前置通知和后置通知都写到一个通知中,组成了环绕通知 2.实现步骤: 2.1 新建一个类实现 MethodInterceptor 接口 public cl ...
- web项目中获取spring的bean对象
Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架,如何在程序中不通过注解的形式(@Resource.@Autowired)获取Spring配置的bean呢? Bean工厂(c ...
- 从XMLHttpRequest中获取请求的URL
在编写Ajax通用错误处理程序时,经常需要记录发生错误的XMLHttpRequest的请求URL.但查询文档,并未找到从XMLHttpRequest中获取请求URL的方法. 在javascript - ...
- 创建dynamics CRM client-side (十三) - 在HTML Web Resource中获取form elements & 获取外部js文件
上一节我们讨论到创建HTML Web Resource. 但是纯HTML的页面不能满足我们的需求, 所以今天我们来做在HTML Web Resource中获取form elements Please ...
- 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 中同时传入文件和其它基本信息结果出现如题异常.在此记录下 ...
- Web网页中动态数据区域的识别与抽取 Dynamical Data Regions Identification and Extraction in Web Pages
Web网页中动态数据区域的识别与抽取 Dynamical Data Regions Identification and Extraction in Web Pages Web网页中动态数据区域的识别 ...
随机推荐
- Android RSA加密解密
概述 RSA是目前最有影响力的公钥加密算法,该算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困 难,因此可以将乘积公开作为加密密钥,即公钥,而两个大素数 ...
- python3中urllib2的问题
import urllib from urllib import request a = urllib.request.Request(url) b = urllib.request.urlopen( ...
- php array_udiff_uassoc比较数组的键值与值
php array_udiff_uassoc 用于带索引检查计算数组的差集,用回调函数比较数据和索引.本文章通过实例向大家介绍array_udiff_uassoc函数的使用方法.需要的码农可以参考一下 ...
- 基于netty的心跳机制实现
前言:在实现过程查找过许多资料,各种波折,最后综合多篇文章最终实现并上线使用.为了减少大家踩坑的时间,所以写了本文,希望有用.对于实现过程中有用的参考资料直接放上链接,可能有些内容相对冗余,不过时间允 ...
- 如何在C#中获得input文本框中的值
前台 <input type="text" id="txt" name="txtn" style="width:213px& ...
- Ubuntu 安装BCM 43142无线网卡驱动
ubuntu14.04 安装 bcm43142无线网卡 用命令lspci 查看无线网卡类型 然后下载对应的无线网卡驱动. 之后,使用下列命令安装,即可搜索无线热点了: sudo apt-get ins ...
- wex5 实战 二维码生成,扫描,蓝牙打印
给人设计了一个小模块,要求是,把一个单号生成二维码,实现扫描查询单号具体信息,并能通过蓝牙把二维码打印出来.功能实现并不复杂,今天一口气把它搞定.来看效果. 一 效果演示: 二.二维码生成 1 在 ...
- PHPwind高级伪静态规则及方法
phpwind iis下伪静态规则[ISAPI_Rewrite]RewriteRule ^(.*)/(.*)-htm-(.*)-(.*)\.html$ $1/$2\.php\?$3=$4Rewrite ...
- [转]使用xcode4 workspace 多个project协同工作
转载地址:http://erlangprogram.com/use-xcode4-workspace 一般的某个应用单独新建一个 project 就可以了,然后把所有的程序文件都放在里面,这个可以 ...
- (转) CCEditBox 编辑框
CCEditBox 编辑框 原文: http://blog.csdn.net/cloud95/article/details/8773470 分类: cocos2d-x 2013-04-08 19:1 ...