过滤器中对请求参数的操作
在工作中经常会有遇到Fitler过滤器的操作,这里就不介绍了,主要说明在过滤器中如何对强求的参数进行获取、操作、最后返回给controller
案例:
在一些app中,为了保护我们的请求安全,我们会对接口的参数,进行加密处理,之后再后端进行解密,在进行强求,但是我们不能每一个接口都去写一个解密方法或者调用解密方法,所有我们可以用aop或者Fitler进行操作,统一处理,这里只说Fitler过滤器
1、自定义一个request类
package com.cesec.utils.encrypt;
import org.apache.commons.lang.StringUtils;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
public class WrapperedRequest extends HttpServletRequestWrapper {
private HttpServletRequest req = null;
private Map<String , String[]> params = new HashMap<String, String[]>();
//用于POST请求
private String body = null;
public WrapperedRequest(HttpServletRequest request) {
// 将request交给父类,以便于调用对应方法的时候,将其输出,其实父亲类的实现方式和第一种new的方式类似
super(request);
this.req = request;
//将参数表,赋予给当前的Map以便于持有request中的参数
this.params.putAll(request.getParameterMap());
}
//重载一个构造方法
public WrapperedRequest(HttpServletRequest request , Map<String, String> extendParams) {
this(request);
addAllParameters(extendParams);//这里将扩展参数写入参数表
}
public WrapperedRequest(HttpServletRequest request, String body) {
super(request);
this.body=body;
}
@Override
public String getParameter(String name) {//重写getParameter,代表参数从当前类中的map获取
String[]values = params.get(name);
if(values == null || values.length == 0) {
return null;
}
return values[0];
}
@Override
public Map<String, String[]> getParameterMap() {
return params;
}
public String[] getParameterValues(String name) {//同上
return params.get(name);
}
public void addAllParameters(Map<String , String>otherParams) {//增加多个参数
for(Map.Entry<String , String>entry : otherParams.entrySet()) {
addParameter(entry.getKey() , entry.getValue());
}
}
public void addParameter(String name , Object value) {//增加参数
if(value != null) {
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)});
}
}
}
@Override
public ServletInputStream getInputStream() throws IOException {
ServletInputStream inputStream = null;
if(StringUtils.isNotEmpty(body)){
inputStream = new PostServletInputStream(body);
}
return inputStream;
}
@Override
public BufferedReader getReader() throws IOException {
String enc = getCharacterEncoding();
if(enc == null) enc = "UTF-8";
return new BufferedReader(new InputStreamReader(getInputStream(), enc));
}
}
2、自定义一个Response
package com.cesec.utils.encrypt;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.*;
public class WrapperedResponse extends HttpServletResponseWrapper {
private ByteArrayOutputStream buffer = null;
private ServletOutputStream out = null;
private PrintWriter writer = null;
public WrapperedResponse(HttpServletResponse resp) throws IOException {
super(resp);
buffer = new ByteArrayOutputStream();// 真正存储数据的流
out = new WapperedOutputStream(buffer);
writer = new PrintWriter(new OutputStreamWriter(buffer,
this.getCharacterEncoding()));
}
/**
* 重载父类获取outputstream的方法
*/
@Override
public ServletOutputStream getOutputStream() throws IOException {
return out;
}
/**
* 重载父类获取writer的方法
*/
@Override
public PrintWriter getWriter() throws UnsupportedEncodingException {
return writer;
}
/**
* 重载父类获取flushBuffer的方法
*/
@Override
public void flushBuffer() throws IOException {
if (out != null) {
out.flush();
}
if (writer != null) {
writer.flush();
}
}
@Override
public void reset() {
buffer.reset();
}
/**
* 将out、writer中的数据强制输出到WapperedResponse的buffer里面,否则取不到数据
*/
public byte[] getResponseData() throws IOException {
flushBuffer();
return buffer.toByteArray();
}
/**
* 内部类,对ServletOutputStream进行包装
*/
private class WapperedOutputStream extends ServletOutputStream {
private ByteArrayOutputStream bos = null;
public WapperedOutputStream(ByteArrayOutputStream stream)
throws IOException {
bos = stream;
}
@Override
public void write(int b) throws IOException {
bos.write(b);
}
@Override
public void write(byte[] b) throws IOException {
bos.write(b, 0, b.length);
}
}
}
3、相关工具类方法
// 解析请求参数为map
private HashMap<String, String> getParams(HttpServletRequest request) {
/
HashMap<String, String> hmParams = getRequestParams(request);
Gson gson = new Gson();
if (hmParams == null || hmParams.size() == 0) {
byte[] bytes = null;
try {
bytes = getDataFromStream(request.getInputStream());
} catch (IOException e) {
e.printStackTrace();
bytes = null;
}
if (bytes != null && bytes.length > 0) {
hmParams = new HashMap<String, String>();
String temp = new String(bytes);
if (temp.startsWith("{") || temp.startsWith("[")) {
hmParams = new Gson().fromJson(temp, new TypeToken<HashMap<String, String>>() {
}.getType());
}
}
}
(这个是我自己的相关解密方法,可根据自己业务调整)
/**String params = hmParams.get(ParamKeyEnum.params.name());
if (params != null && params.length() > 0) {
try {
params = DesUtils.decrypt(params);
} catch (Exception e) {
logger.errorWithNoTrans("解密params数据发生错误!", logger, e);
return null;
}
logger.debug("解密后的params数据为:" + params, logger);
*/
// 解析参数为HashMap
if (params.startsWith("{") || params.startsWith("[")) {
hmParams = new Gson().fromJson(params, new TypeToken<HashMap<String, String>>() {
}.getType());
hmParams.remove(ParamKeyEnum.params.name());
hmParams.put(ParamKeyEnum.params.name(), params);
}
}
return hmParams;
}
//获取get请求中的数据
public HashMap<String, String> getRequestParams(HttpServletRequest request) {
HashMap<String, String> hmParams = new HashMap<String, String>();
try {
String encoding = request.getCharacterEncoding();
// tomcat需要配置编码为utf-8
encoding = encoding == null || "".equals(encoding) ? "UTF-8" : encoding;
Enumeration<String> parameterNames = request.getParameterNames();
while (parameterNames.hasMoreElements()) {
String paramName = parameterNames.nextElement();
String value = request.getParameter(paramName);
hmParams.put(paramName, new String(value.getBytes(encoding), "UTF-8"));
}
} catch(Exception e) {
LogUtils.errorWithNoTrans("[getParams][HttpServletRequest]解析请求参数出错",logger,e);
}
return hmParams;
}
//获取body中的数据(post请求的数据)
public static byte[] getDataFromStream(InputStream input) {
DataInputStream dataInputStream = null;
ByteArrayOutputStream byteStream = null;
try {
dataInputStream = new DataInputStream(input);
byteStream = new ByteArrayOutputStream();
byte bufferByte[] = new byte[1024 * 8];
for (int l = -1; (l = dataInputStream.read(bufferByte)) > -1;) {
byteStream.write(bufferByte, 0, l);
byteStream.flush();
}
byte inByte[] = byteStream.toByteArray();
if (inByte.length == 0) {
inByte = null;
}
return inByte;
} catch(Exception e) {
LogUtils.errorWithNoTrans("[getDataFromStream]获取输入流的数据时失败",logger,e);
return null;
} finally {
try {
if (dataInputStream != null) {
dataInputStream.close();
dataInputStream = null;
}
if (byteStream != null) {
byteStream.close();
byteStream = null;
}
} catch (IOException e) {
}
}
}
4、获取参数进行相关操作
public class EncyptFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
String contentType = request.getContentType();//请求方式
try {
// 解析请求参数为map
WrapperedResponse wrapResponse = new WrapperedResponse(response);//创建自定义的response类
WrapperedRequest wrapRequest = null; //创建自定义的Request类
//带有图片的请求
if (StringUtils.isNotEmpty(contentType) && (contentType.contains("multipart/form-data"))) {
MultipartResolver resolver = new CommonsMultipartResolver(request.getSession().getServletContext());
MultipartHttpServletRequest paramsTest = resolver.resolveMultipart(request);
//获取前段请求的数据
MultiValueMap<String, MultipartFile> multiFileMap = paramsTest.getMultiFileMap();//获取所有值
String params = paramsTest.getParameter("params");//获取key为params的值 与自己业务相关这里是加密参数
MultipartFile file = paramsTest.getFile("file");//获取图片信息
//获取request中的值转为map
HashMap<String, String> hmParams = getRequestParams(paramsTest);
// 拿到自己想要的参数,可以做自己想要的操作
//列如:对参数进行了解密操作
if (hmParams != null) {
HttpServletRequest revertServletRequest = (HttpServletRequest) paramsTest;
wrapRequest = new WrapperedRequest(revertServletRequest, JSONObject.toJSONString(hmParams));
wrapRequest.addAllParameters(hmParams);
for (Map.Entry<String, List<MultipartFile>> entry : multiFileMap.entrySet()) {
wrapRequest.addParameter(entry.getKey(), entry.getValue());
}
filterChain.doFilter(wrapRequest, wrapResponse);
}
} else if (StringUtils.isNotEmpty(contentType) && contentType.contains("application/json")) {
Map<String, String> params = getParams(request);
if (!ObjectUtils.isEmpty(params )) {
wrapRequest = new WrapperedRequest(request, JSONObject.toJSONString(params));
filterChain.doFilter(wrapRequest, wrapResponse);
} else {
LogUtils.errorWithNoTrans("非法请求", logger, new Exception("非法请求"));
response.getWriter().close();
return;
}
} else {
Map<String, String> params = getParams(request, dto);
wrapRequest = new WrapperedRequest(request, params);
filterChain.doFilter(wrapRequest, wrapResponse);
}
} catch (Exception e) {
LogUtils.errorWithNoTrans("请求加密处理异常,e=" + e.getLocalizedMessage(), logger, e);
}
}
@Override
public void destroy() {
}
}