簡體   English   中英

POST 參數 null,但存在於正文中

[英]POST parameter null, but present in body

我有一個在本地運行良好的應用程序,但在客戶端它崩潰了,因為 POST 參數是 null。

((HttpServletRequest)request).getParameter("dtid");

這返回 null。

所以我添加了一個過濾器來記錄請求的 GET/POST/BODY。 在本地,日志如下所示:

[方法:POST] [請求 URI:/peps/zkau] [請求參數:{dtid =z_0n8, uuid_0=x38Pz, data_0={"pageX":372,"pageY":103,"which":1,"x ":40.79998779296875,"y":4}, cmd_0=onClick}] [請求正文:] [遠程地址:0:0:0:0:0:0:0:1]

我在請求參數中有 dtid 並且正文是空的。 在客戶端,相同的日志如下所示:

[方法:POST] [請求 URI:/peps/zkau] [請求參數:{} ] [請求體:dtid=z_cb50&cmd_0=onOpen&uuid_0=l2sT30&data_0=%7B%22open%22%3Atrue%2C%22reference%22%3A%22l2sT20 %22%7D&cmd_1=onClick&uuid_1=l2sT40&data_1=%7B%22pageX%22%3A323%2C%22pageY%22%3A138%2C%22which%22%3A1%2C%22x%22%3A323%2C%22y%22%3A138% 7D&cmd_2=onOpen&uuid_2=l2sT30&data_2=%7B%22open%22%3Afalse%7D] [遠程地址:xxxx]

參數是一個空的map,但是body是滿的。 身體似乎沒有經過處理,這可能是什么原因? 為什么body沒有解析並注入參數map?

謝謝

這是我的過濾器:

public class PepsParamFilter implements Filter {

    private static final Logger LOG = Logger.getLogger(PepsParamFilter.class.getName());

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

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        try {
            HttpServletRequest httpServletRequest = (HttpServletRequest) request;

            Map<String, String> requestMap = this.getTypesafeRequestMap(httpServletRequest);
            BufferedRequestWrapper bufferedReqest = new BufferedRequestWrapper(httpServletRequest);            

            chain.doFilter(bufferedReqest, response);

             //Request
                final StringBuilder reqMessage = new StringBuilder("").append("[METHOD:")
                        .append(httpServletRequest.getMethod())                        
                        .append("] [REQUEST URI:")
                        .append(httpServletRequest.getRequestURI())                        
                        .append("] [REQUEST PARAMETERS:").append(requestMap)
                        .append("] [REQUEST BODY:")
                        .append(bufferedReqest.getRequestBody())
                        .append("] [REMOTE ADDRESS:")
                        .append(httpServletRequest.getRemoteAddr()).append("]");
                if(!httpServletRequest.getRequestURI().endsWith(".gif")
                    && !httpServletRequest.getRequestURI().endsWith(".png")
                    && !httpServletRequest.getRequestURI().endsWith(".css")
                    ) {
                    LOG.info(reqMessage);
                }



        } catch (Throwable a) {
            LOG.error(a.getMessage(),a);
        }
    }

    private Map<String, String> getTypesafeRequestMap(HttpServletRequest request) {
        Map<String, String> typesafeRequestMap = new HashMap<String, String>();
        Enumeration<?> requestParamNames = request.getParameterNames();
        while (requestParamNames.hasMoreElements()) {
            String requestParamName = (String) requestParamNames.nextElement();
            String requestParamValue = request.getParameter(requestParamName);
            typesafeRequestMap.put(requestParamName, requestParamValue);
        }
        return typesafeRequestMap;
    }

    @Override
    public void destroy() {
    }

    private static final class BufferedRequestWrapper extends
            HttpServletRequestWrapper {

        private ByteArrayInputStream bais = null;
        private ByteArrayOutputStream baos = null;
        private BufferedServletInputStream bsis = null;
        private byte[] buffer = null;

        public BufferedRequestWrapper(HttpServletRequest req)
                throws IOException {
            super(req);
            // Read InputStream and store its content in a buffer.
            InputStream is = req.getInputStream();
            this.baos = new ByteArrayOutputStream();
            byte buf[] = new byte[1024];
            int letti;
            while ((letti = is.read(buf)) > 0) {
                this.baos.write(buf, 0, letti);
            }
            this.buffer = this.baos.toByteArray();
        }

        @Override
        public ServletInputStream getInputStream() {
            this.bais = new ByteArrayInputStream(this.buffer);
            this.bsis = new BufferedServletInputStream(this.bais);

            return this.bsis;
        }

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

        String getRequestBody() throws IOException {
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    this.getInputStream()));
            String line = null;
            StringBuilder inputBuffer = new StringBuilder();
            do {
                line = reader.readLine();
                if (null != line) {
                    inputBuffer.append(line.trim());
                }
            } while (line != null);
            reader.close();
            return inputBuffer.toString().trim();
        }

    }

    private static final class BufferedServletInputStream extends
            ServletInputStream {

        private ByteArrayInputStream bais;

        public BufferedServletInputStream(ByteArrayInputStream bais) {
            this.bais = bais;
        }

        @Override
        public int available() {
            return this.bais.available();
        }

        @Override
        public int read() {
            return this.bais.read();
        }

        @Override
        public int read(byte[] buf, int off, int len) {
            return this.bais.read(buf, off, len);
        }

    }

    public class TeeServletOutputStream extends ServletOutputStream {

        private final TeeOutputStream targetStream;

        public TeeServletOutputStream(OutputStream one, OutputStream two) {
            targetStream = new TeeOutputStream(one, two);
        }

        @Override
        public void write(int arg0) throws IOException {
            this.targetStream.write(arg0);
        }

        public void flush() throws IOException {
            super.flush();
            this.targetStream.flush();
        }

        public void close() throws IOException {
            super.close();
            this.targetStream.close();
        }
    }


}

Servlet-spec 的第 3.1.1節指出:

3.1.1 參數可用時

以下是在將表單數據填充到參數集之前必須滿足的條件:

  1. 請求是 HTTP 或 HTTPS 請求。
  2. HTTP 方法是 POST。
  3. 內容類型為 application/x-www-form-urlencoded。
  4. servlet 已對請求 object 的任何 getParameter 系列方法進行了初始調用。

如果不滿足條件且 post 表單數據未包含在參數集中,則 post 數據必須仍可通過請求對象的輸入 stream 提供給 servlet。 如果滿足條件,則無法再從請求對象的輸入 stream 直接讀取發布表單數據。

您必須檢查這些條件中的任何一個是否適用於您的本地或客戶端系統。

可能還有其他過濾器(在您之前的過濾器鏈中),它們已經處理了請求正文,或者更改了內容類型,或者之前訪問了 getParameter* 方法之一,或者包裝了請求......(你明白了)

本質上,這兩種狀態都是有效的,具體取決於您之前的請求發生了什么。

首先要檢查的是瀏覽器是否發送相同的請求(/正文)和標頭。 例如在瀏覽器的開發者工具中。 如果它們相同,請檢查您的 web.xml 以獲取其他過濾器(例如,本地開發環境和生產環境之間的安全過濾器通常不同)。

通過 POST 調用,參數將在請求正文中發送,這發生在您服務器的日志中。 因此,您需要獲取請求正文才能訪問所需的參數,請參閱this question on how to get post data。

暫無
暫無

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

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