通过HttpServletRequestWrapper修改Header和Body内容实现前后端传输内容加密

/ 后端 / 没有评论 / 217浏览

达到目的

客户端发送AES加密后的内容请求(内容类型application/octet-stream;data=1) ====>服务端解密请求内容,分发到controller(接受处理内容类型application/json) ====>返回json响应结果

请求包装类(修改Header,解密请求内容)

import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
import cn.hutool.json.JSONUtil;
import com.example.tomcattest.model.UserInfo;
import org.apache.tomcat.util.http.fileupload.IOUtils;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;

public class AesHttpServletRequestWrapper extends HttpServletRequestWrapper {

    private byte[] requestBody;
    private Map<String, String> headerMap = new HashMap<>();

    static AES aes = SecureUtil.aes("aaaaaaaaaaaaaaaa".getBytes(StandardCharsets.UTF_8));

    public AesHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        if (null == this.requestBody) {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            IOUtils.copy(request.getInputStream(), baos);
            this.requestBody = baos.toByteArray();
        }
    }


    //修改内容----------------------------------------------------
    @Override
    public ServletInputStream getInputStream() throws IOException {
        String body = new String(requestBody);
        body = aes.decryptStr(body);
        final ByteArrayInputStream stream = new ByteArrayInputStream(body.getBytes(StandardCharsets.UTF_8));

        ServletInputStream inputStream = 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 stream.read();
            }
        };
        return inputStream;
    }
    //修改内容----------------------------------------------------


    //修改header----------------------------------------------------
    public void addHeader(String name, String value) {
        headerMap.put(name, value);
    }

    @Override
    public String getHeader(String name) {
        String headerValue = super.getHeader(name);
        if (headerMap.containsKey(name)) {
            headerValue = headerMap.get(name);
        }
        return headerValue;
    }

    @Override
    public Enumeration<String> getHeaderNames() {
        List<String> names = Collections.list(super.getHeaderNames());
        for (String name : headerMap.keySet()) {
            names.add(name);
        }
        return Collections.enumeration(names);
    }

    @Override
    public Enumeration<String> getHeaders(String name) {
        List<String> values = Collections.list(super.getHeaders(name));
        if (headerMap.containsKey(name)) {
            values = Arrays.asList(headerMap.get(name));
        }
        return Collections.enumeration(values);
    }
    //修改header----------------------------------------------------
  
    //测试并生成请求内容
    public static void main(String[] args) {
        UserInfo userInfo = new UserInfo();
        userInfo.setId(1);
        userInfo.setName("高杨");
        String encryptHex = aes.encryptHex(JSONUtil.toJsonStr(userInfo));
        System.out.println(encryptHex);
        String decryptStr = aes.decryptStr(encryptHex);
        System.out.println(decryptStr);
    }

过滤器

public class AesFilter implements Filter {

    String aesContentType = MediaType.APPLICATION_OCTET_STREAM_VALUE + ";data=1";

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String contentType = request.getContentType();
        if (!contentType.equals(aesContentType)) {
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }

        AesHttpServletRequestWrapper aesHttpServletRequestWrapper = new AesHttpServletRequestWrapper(request);
        aesHttpServletRequestWrapper.addHeader("content-type", MediaType.APPLICATION_JSON_VALUE);
        filterChain.doFilter(aesHttpServletRequestWrapper, servletResponse);
    }
}

注册过滤器

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Bean
    public FilterRegistrationBean xssRegistrationBeanDefaultFilter() {
        FilterRegistrationBean bean = new FilterRegistrationBean();
        bean.setFilter(new AesFilter());
        bean.setUrlPatterns(Arrays.asList("/*"));
        bean.setOrder(-1);
        return bean;
    }
}

服务端接口

简单的处理json内容类型的RESTFUL风格的Http接口

@RestController
public class AesController {

    @PostMapping(value = "/aes/test")
    public UserInfo test(@RequestBody(required = false) UserInfo userInfo) {
        return userInfo;
    }
}

进行测试

成功返回解密内容