项目组某个接口的新需求,需要调用该接口的信息加密,不能显示明文的。加密都好说,调用方使用RSA公钥加密,服务端使用RSA私钥解密,这个不在这赘述了。
服务端解密过程我的思路是使用过滤器国女某些特别的请求,例如登录接口等。在过滤器内将加密的信息解密,再把解密的信息放到request内,之后controller使用解密的信息进行后续的操作。但是遇到了一些问题,问题如下:
1、过滤器中直接对request使用setAttribute方法,在之后的操作中,不能通过request.getParameter()获得对应参数。如果使用这种方法,对现有代码改动比较大,PASS。
2、为了使后续能够通过request.getParameter()获得参数,需自定义一个request参数处理类,RequestParameterWrapper.java,代码如下。
public class RequestParameterWrapper extends HttpServletRequestWrapper{
private Map<String,String[]> params = null;
//构造方法
public RequestParameterWrapper(HttpServletRequest request){
super(request);
this.params = new HashMap<>(request.getParameterMap());
}
//添加参数的方法
public void addParameters(Map<String,Object> extraParams){
for(Entry<String,Object> entry : extraParams){
addParameters(entry.getKey(),entry.getValue());
}
}
//这四个重写的方法是很重要的!!!只有重写了这四个方法,后续才能在这个request中获取到对应的参数
@Override
public String getParameter(String name){
String[] values = params.get(name);
if(values == null || values.length == 0){
return null;
}
return values[0];
}
@Override
public Map<String,String[]> getParameterMap(){
return params;
}
@Override
public String[] getParamaterValues(String name){
return params.get(name);
}
//一般网上的方法都没有重写这个方法,如果不重写这个方法,
//而且controller中的参数为javaBean时,bean中的属性将不会自动绑定,下面会详细讲解这个
@Override
public Enumeration<String> getParameterNames(){
Vector<String> nameList = new Vector<String>();
for(Entry<String,String[]> entry: params.entrySet()){
nameList.add(entry.getKey());
}
return nameList.elements();
}
public void addParameters(String name,Object value){
if(null != value){
if(value instanceod String[]){
params.put(name,(String[]) value);
}else if(value instanceod String){
params.put(name,new String[]{(String value)});
}else{
params.put(name,new String[]{String.valueOf(value)});
}
}
}
}
写完这个类之后,在filter中chain.doFilter(arg1,response)第一个参数arg1,直接写这个类的对象即可,这个网上一大堆。
为何不重写getParameterNames()方法会导致自动绑定不上bean的属性?看源码。这个多余的源码我就不赘述,直接看问题的所在,看org.springframework.web.util.WebUtils.getParametersStartingWith()这个方法,这个方法里第二行就是调用request.getParameterNames()方法获取所有参数名称,之后在根据这个参数名称列表获取参数进行绑定操作,如果不重写这个方法,那么获取到的还是原来的参数列表,自然无法绑定参数。
public static Map<String, Object> getParametersStartingWith(ServletRequest request, String prefix) {
Assert.notNull(request, "Request must not be null");
Enumeration<String> paramNames = request.getParameterNames();
Map<String, Object> params = new TreeMap<String, Object>();
if (prefix == null) {
prefix = "";
}
while (paramNames != null && paramNames.hasMoreElements()) {
String paramName = paramNames.nextElement();
if ("".equals(prefix) || paramName.startsWith(prefix)) {
String unprefixed = paramName.substring(prefix.length());
String[] values = request.getParameterValues(paramName);
if (values == null || values.length == 0) {
// Do nothing, no values found at all.
}
else if (values.length > 1) {
params.put(unprefixed, values);
}
else {
params.put(unprefixed, values[0]);
}
}
}
return params;
}
网友评论