您的位置:首页 > 编程语言 > Java开发

关于在Spring过滤器中修改request的参数值遇到的问题(三)

2017-06-21 23:07 711 查看
继上一遍为背景

问题描述:

成功解密了reqeust中的参数后,在控制层Controller中获取到的参数,是没有解密的参数。例如:在过滤器中修改 参数名为username 的参数值432895328195783915781(一串加密的密文) 为 xiaomin(解密后的明文),在Cotroller中获取到的依然是加密后的密文432895328195783915781。

问题定位

百度,没有,心酸,跑不掉,一步一步debugger,终于发现

在SpringMVC框架中,request到controller层的数据bind(绑定)中,用到该类的方法org.springframework.web.method.annotation.RequestParamMethodArgumentResolver

@Override
protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest webRequest) throws Exception {
HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
MultipartHttpServletRequest multipartRequest =
WebUtils.getNativeRequest(servletRequest, MultipartHttpServletRequest.class);
Object arg; // 将被绑定的值
.
.
.
if (multipartRequest != null) {
List<MultipartFile> files = multipartRequest.getFiles(name);
if (!files.isEmpty()) {
arg = (files.size() == 1 ? files.get(0) : files);
}
}
if (arg == null) { // 方法走了该判断体
String[] paramValues = webRequest.getParameterValues(name);
if (paramValues != null) {
arg = (paramValues.length == 1 ? paramValues[0] : paramValues);
}
}
}


如上注释,方法在一定条件下走了String[] paramValues = webRequest.getParameterValues(name);这一段代码,debugger发现,

这段代码走的的真正实现竟然是web容器Tomcat提供的request包装类org.apache.catalina.connector.RequestFacade中的方法。(因为这里的WebUtils.getNativeRequest(servletRequest, MultipartHttpServletRequest.class)最后返回了一个Tomcat提供的request包装类)

@Override
public String[] getParameterValues(String name) {

if (request == null) {
throw new IllegalStateException(
sm.getString("requestFacade.nullRequest"));
}

String[] ret = null;
if (SecurityUtil.isPackageProtectionEnabled()){
ret = AccessController.doPrivileged(
new GetParameterValuePrivilegedAction(name));
if (ret != null) {
ret = ret.clone();
}
} else {
ret = request.getParameterValues(name);
}

return ret;
}


而该Tomcat的request包装类中的参数,确实是没有解密之前的值。由此猜测(个人猜测,不对的请指点迷津,感激) 1.服务器在接受请求时,Spring和Tomcat各自都创建了一个request的包装类(可以发现都实现了HttpServletRequest接口),在没有修改rquest参数时,这两个包装类几乎一样(指参数值都是一致的),当我在过滤器中修改了Spring的rquest包装类参数值,tomcat的request包装类是没有修改的。2.在SpringMVC的数据绑定中,应为某些原因,需要从tomcat的request包装类中获取参数值。这就导致了上述问题的发生。

4.解决方案

在之前的自定义包装类中(继承了ServletRequestWrapper)重写 getParameterValues(String name)方法

import org.apache.catalina.util.ParameterMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.util.Map;

public class ParameterRequestWrapper extends HttpServletRequestWrapper {

private ParameterMap<String, String[]> params;

@SuppressWarnings("all")
public ParameterRequestWrapper(HttpServletRequest request) {
super(request);
params = (ParameterMap) request.getParameterMap();
// TODO Auto-generated constructor stub
}

@Override
public String getParameter(String name) {
// TODO Auto-generated method stub
String[] values = params.get(name);
if (values == null || values.length == 0) {
return null;
}
return values[0];
}

@Override
public Map<String, String[]> getParameterMap() {
// TODO Auto-generated method stub
return params;
}

// 就是该方法
@Override
public String[] getParameterValues(String name) {
return params.get(name);
}

public void addParameter(String name, Object value) {
if (value != null) {
params.setLocked(false);
if (value instanceof String[]) {
params.put(name, (String[]) value);
} else if (value instanceof String) {
params.put(name, new String[] { (String) value });
} else {
params.put(name, new String[] { String.valueOf(value) });
}
params.setLocked(true);
}
}
}


解决问题,如有不对的地方,还请高人路过指点。

4000
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐