在Spring MVC中使用HttpServletRequest之前替换/准备原始POST数据

时间:2015-09-12 18:40:31

标签: java spring-mvc

我有基于api的客户端 - 服务器应用程序,php + yii作为后端。我的目标是使后端端口从php到java(与客户端的旧查询兼容)。

我选择了Spring MVC框架,但却因解密原始帖子数据而陷入困境。问题是旧客户端使用自定义加密算法,因此HttpServletRequest.getParameterMap()不会返回有效的地图。

所以,我的问题是:在这种情况下,在使用request.getParameterMap()方法进行纯业务逻辑之前,更换/准备原始数据(解密)的最佳解决方案是什么?

控制器代码是这样的:

@RestController
@RequestMapping(value = "/", method = RequestMethod.POST)
public class ApiController {

    @RequestMapping
    @ResponseBody
    public String process(HttpServletRequest request) {
        ApiQueryResponse queryResponse = new ApiQueryResponse();

        try {
            // request = APIEncryptor.decrypt(request);         // 1
            // now working with request.getParameterMap()       // 2
            // ...
            queryResponse.setText(APIEncryptor.crypt(...))
        } catch (Exception e) {
            queryResponse.setError(e.getMessage());
        }

        return queryResponse.asText();
    }

    ...

}

APIEncryptor代码是这样的:

public class ApiEncryptor {
    public static ApiQueryData encrypt(Java Object) {
        // custom encryption algorithm...
        return Raw data string;
    }

    // input post data: 103klg20fsl2g2fsldkfj20f9isjf
    // output post data: a=1&b=2&c=3&d=some_text

    public static ApiQueryData decrypt(Raw post data...) {
        // decrypt algorithm...
        return request; // HttpServletRequest object with valid post data
        // after this action, .getParameter() will produce valid data
    }
}

注意:我知道request.getInputStream()之类的方法存在,但我现在不需要它。我需要知道有没有办法在使用HttpServletRequest参数getter之前准备帖子数据?或者(无论如何)我需要从请求中获取一次数据并执行我想要的操作(例如,通过getReader())?

2 个答案:

答案 0 :(得分:1)

  

处理解密逻辑的最佳方法是在http过滤器内   (使用spring MVC)如下所示。此过滤器解密请求   收到请求后立即到达服务器   控制器方法。

import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.filter.OncePerRequestFilter;

public class DecryptionFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        request = ApiEncryptor.decrypt(request);

        filterChain.doFilter(request, response);
    }

}

答案 1 :(得分:0)

  

HttpServletRequest在具有Spring Boot和Java 8的Filter中的控制器之前解密

public class RequestWrapper extends HttpServletRequestWrapper {

private final String body;

public RequestWrapper(HttpServletRequest request) throws Exception {
    super(request);

    StringBuilder stringBuilder = new StringBuilder();
    BufferedReader bufferedReader = null;
    try {
        InputStream inputStream = request.getInputStream();
        if (inputStream != null) {
            bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            char[] charBuffer = new char[128];
            int bytesRead = -1;
            while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
                stringBuilder.append(charBuffer, 0, bytesRead);
            }
        } else {
            stringBuilder.append("");
        }
    } catch (IOException ex) {
        throw ex;
    } finally {
        if (bufferedReader != null) {
            try {
                bufferedReader.close();
            } catch (IOException ex) {
                throw ex;
            }
        }
    }
    String encryptData = stringBuilder.toString();
    String deCryptData = null;
    if (encryptData != null && !encryptData.isEmpty()) {
        deCryptData = MD5Utils.decrypt(encryptData);
        if (deCryptData == null) {
            //logger.error("Exception occured inside MD5Utils.decrypt(encryptData) - Request Body not valid : ");
        }
    }
    body = deCryptData;
}

@Override
public ServletInputStream getInputStream() throws IOException {
    final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
    ServletInputStream servletInputStream = new ServletInputStream() {
        public int read() throws IOException {
            return byteArrayInputStream.read();
        }

        @Override
        public boolean isFinished() {
            // TODO Auto-generated method stub
            return false;
        }

        @Override
        public boolean isReady() {
            // TODO Auto-generated method stub
            return false;
        }

        @Override
        public void setReadListener(ReadListener listener) {
            // TODO Auto-generated method stub

        }
    };
    return servletInputStream;
}

@Override
public BufferedReader getReader() throws IOException {
    return new BufferedReader(new InputStreamReader(this.getInputStream()));
}

public String getBody() {
    return this.body;
}

}

过滤器类

public class MyFilter implements Filter {
  @Override
  public void doFilter(ServletRequest request, ServletResponse response,
        FilterChain chain) throws IOException, ServletException {

    /* wrap the request in order to read the inputstream multiple times */
    HttpServletRequest httpServletRequest = (HttpServletRequest) request;
    HttpServletResponse httpServletResponse = (HttpServletResponse) response;
    request = new RequestWrapper(httpServletRequest);  

    chain.doFilter(request, response);
  }
}