filter处理request解密验签response加密加签
实现思路
1. 通过filter实现
2. 由于serlevt的request和respon无法直接修改,因此通过requestWrapper和responseWrapper实现即:获取到原始request中需要的参数,通过wrapper生成解封装之后的request调用业务处理controller,调用之后获取到原始response,获取到原始response,通过wrapper封装之后返回。
3. requestWrapper包装要点:如果是参数传递需要重写父类的getParameterNames、getParameter、getParameterValues、getParameterMap方法,把这些方法的返回替换为自己设置的参数,这样在后续调用Controller时会通过这些方法获取到替换后的参数;如果是body传值,则需要重写getInputStream、getReader等。
4. responseWrapper包装要点:要重写父类的getOutputStream、getWriter、flushBuffer方法,使之返回自己设置response。
源码实现
Filter
@WebFilter(filterName = "CmbRequestFilter", urlPatterns = "/third/openapi/cmb*/*")
@Configuration
@Order(-1)
@Slf4j
public class CmbRequestFilter implements Filter {
@Resource
private CmbProperties cmbAggPayProperties;
@Override
public void init(FilterConfig filterConfig) {
log.info("cmb request filter...");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
ModifyParamsRequestWrapper requestWrapper = new ModifyParamsRequestWrapper((HttpServletRequest) request);
ModifyBodyResponseWrapper responseWrapper = new ModifyBodyResponseWrapper((HttpServletResponse) response);
Map<String, String> flatParamMap = requestWrapper.getFlatParamMap();
CallBackResp returnBizContent;
if (checkSign(flatParamMap)) {
String bizContent = flatParamMap.get("biz_content");
Map<String, String> map = JSONUtil.toBean(bizContent, Map.class);
requestWrapper.setParameterMap(map);
chain.doFilter(requestWrapper, responseWrapper);
String entityStr = responseWrapper.getContent();
returnBizContent = JSONUtil.toBean(entityStr, CallBackResp.class);
} else {
returnBizContent = CallBackResp.FAIL("验签失败");
}
ServletOutputStream out = response.getOutputStream();
out.write(JSONUtil.toJsonStr(wrapResponse(returnBizContent)).getBytes(StandardCharsets.UTF_8));
out.flush();
}
RequestWrapper
import cn.hutool.core.map.MapUtil;
import jakarta.servlet.ReadListener;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import org.apache.commons.io.IOUtils;
import java.io.*;
import java.util.Enumeration;
import java.util.Map;
import java.util.Vector;
public class ModifyParamsRequestWrapper extends HttpServletRequestWrapper {
private Map<String, String[]> parameterMap;
private byte[] requestBody;
private HttpServletRequest request;
public ModifyParamsRequestWrapper(HttpServletRequest request) {
super(request);
this.request = request;
this.parameterMap = request.getParameterMap();
}
@Override
public Enumeration<String> getParameterNames() {
return new Vector<>(parameterMap.keySet()).elements();
}
@Override
public String getParameter(String name) {
String[] values = parameterMap.get(name);
if (values == null || values.length == 0) {
return null;
}
return values[0];
}
@Override
public String[] getParameterValues(String name) {
String[] values = parameterMap.get(name);
if (values == null || values.length == 0) {
return null;
}
return values;
}
@Override
public Map<String, String[]> getParameterMap() {
return parameterMap;
}
@Override
public ServletInputStream getInputStream() throws IOException {
if (null == this.requestBody) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
IOUtils.copy(request.getInputStream(), baos);
this.requestBody = baos.toByteArray();
}
final ByteArrayInputStream bais = new ByteArrayInputStream(requestBody);
return new ServletInputStream() {
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {}
@Override
public int read() throws IOException {
return bais.read();
}
};
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
public Map<String, String> getFlatParamMap() {
Map<String, String> map = MapUtil.newHashMap(parameterMap.size());
for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
map.put(entry.getKey(), entry.getValue()[0]);
}
return map;
}
public void setParameterMap(Map<String, String> flagParamMap) {
Map<String, String[]> map = MapUtil.newHashMap(flagParamMap.size());
for (Map.Entry<String, String> entry : flagParamMap.entrySet()) {
String[] array = {entry.getValue()};
map.put(entry.getKey(), array);
}
this.parameterMap = map;
}
ResponseWrapper
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.WriteListener;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpServletResponseWrapper;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
public class ModifyBodyResponseWrapper extends HttpServletResponseWrapper {
private ByteArrayOutputStream byteArrayOutputStream;
private ServletOutputStream servletOutputStream;
private PrintWriter writer;
public ModifyBodyResponseWrapper(HttpServletResponse response) {
super(response);
byteArrayOutputStream = new ByteArrayOutputStream();
servletOutputStream = new WrapperOutputStream(byteArrayOutputStream);
writer = new PrintWriter(byteArrayOutputStream);
}
@Override
public ServletOutputStream getOutputStream() {
return servletOutputStream;
}
@Override
public PrintWriter getWriter() {
return writer;
}
public String getContent() throws IOException {
flushBuffer();
return byteArrayOutputStream.toString();
}
@Override
public void flushBuffer() throws IOException {
if (servletOutputStream != null) {
servletOutputStream.flush();
}
if (writer != null) {
writer.flush();
}
}
class WrapperOutputStream extends ServletOutputStream {
private ByteArrayOutputStream baos;
public WrapperOutputStream(ByteArrayOutputStream out) {
super();
this.baos = out;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setWriteListener(WriteListener writeListener) {}
@Override
public void write(int b) throws IOException {
this.baos.write(b);
}
@Override
public void write(byte[] b) throws IOException {
this.baos.write(b);
}
}