簡體   English   中英

在Spring MVC中使用HttpServletRequest之前替換/准備原始POST數據

[英]replace/prepare raw POST data before using HttpServletRequest in 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參數獲取器之前准備發布數據嗎? 或者(無論如何)我需要一次從請求中獲取發布數據,然后做我想做的事情(例如,通過getReader())?

處理解密邏輯的最佳方法是在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);
    }

}

使用Spring Boot和Java 8過濾器中的HttpServletRequest解密之前的控制器

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM