filter 实现 请求数据与返回数据的加解密

因为项目需要,需要对请求数据数据和返回数据统一做加解密的处理。本文重点介绍一下,在过滤器中修改请求数据和返回数据,不详细介绍加解密的实现。

原理

这里写图片描述

如上图所示,输出流并不像我们想象的那样,必经过滤器,然后返回给客户端,这样就会有一个问题,当我们在过滤器对返回数据做处理,然后写到客户端时,此时可能输出流已经被相应到客户端了。下图是我们要实现的效果。
这里写图片描述
使用自己包装好的repsonse,以达到sevlet直接向客户端返回数据失效的效果。这样我们就可以在过滤器中,对我们的请求数据和返回数据进行处理,使之完全在我们的控制范围内。

源码

public class AESFilter implements Filter {
private final Logger LOG = LoggerFactory.getLogger(AESFilter.class);
/**
* aes 密匙
*/
@Value(“ fpfkxt.aes.key)privateStringAESKEY;/AES/@Value( {sfqyaes}”)
private String SFQYAES;

@Override
public void init(FilterConfig filterConfig) throws ServletException {

}

@Override
public void doFilter(ServletRequest request, ServletResponse response,
        FilterChain chain) throws IOException, ServletException {
    // 如果启用aes加密解密
    if (CommonConst.SFQYAES_Y.equals(SFQYAES)) {
        String requestBody = getRequestBody((HttpServletRequest) request);
        //解密请求报文
        String requestBodyMw = CryptionUtil.aesDecrypt(requestBody.trim(),
                AES_KEY);
        LOG.debug("解密请求数据:" + requestBodyMw);

        WrapperedResponse wrapResponse = new WrapperedResponse(
                (HttpServletResponse) response);
        WrapperedRequest wrapRequest = new WrapperedRequest(
                (HttpServletRequest) request, requestBodyMw);

        chain.doFilter(wrapRequest, wrapResponse);

        byte[] data = wrapResponse.getResponseData();
        LOG.debug("原始返回数据: " + new String(data, "utf-8"));
        // 加密返回报文
        String responseBodyMw = CryptionUtil.aesEncrypt(data, AES_KEY); 
        LOG.debug("加密返回数据: " + responseBodyMw);
        writeResponse(response, responseBodyMw);
    } else {
        chain.doFilter(request, response);
    }
}

private void writeResponse(ServletResponse response, String responseString)
        throws IOException {
    PrintWriter out = response.getWriter();
    out.print(responseString);
    out.flush();
    out.close();
}

@Override
public void destroy() {
    // TODO Auto-generated method stub

}

/**
 * @param req
 * @return
 */
private String getRequestBody(HttpServletRequest req) {
    try {
        BufferedReader reader = req.getReader();
        StringBuffer sb = new StringBuffer();
        String line = null;
        while ((line = reader.readLine()) != null) {
            sb.append(line);
        }
        String json = sb.toString();
        return json;
    } catch (IOException e) {
        LOG.error("验签时请求体读取失败", e);
    }
    return "";
}

}

public class WrapperedRequest extends HttpServletRequestWrapper {
/**
* 请求报文
*/
private String requestBody = null;
HttpServletRequest req = null;

public WrapperedRequest(HttpServletRequest request) {
    super(request);
    this.req = request;
}

public WrapperedRequest(HttpServletRequest request, String requestBody) {
    super(request);
    this.requestBody = requestBody;
    this.req = request;
}

/*
 * (non-Javadoc)
 * 
 * @see javax.servlet.ServletRequestWrapper#getReader()
 */
@Override
public BufferedReader getReader() throws IOException {
    return new BufferedReader(new StringReader(requestBody));
}

/*
 * (non-Javadoc)
 * 
 * @see javax.servlet.ServletRequestWrapper#getInputStream()
 */
@Override
public ServletInputStream getInputStream() throws IOException {
    return new ServletInputStream() {
        private InputStream in = new ByteArrayInputStream(
                requestBody.getBytes(req.getCharacterEncoding()));

        @Override
        public int read() throws IOException {
            return in.read();
        }
    };
}

}

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);
    }
}

}

  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值