Java-web filter处理request解密验签response加密加签

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);
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值