Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/http/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 修改HttpServletRequest正文_Java_Http_Request - Fatal编程技术网

Java 修改HttpServletRequest正文

Java 修改HttpServletRequest正文,java,http,request,Java,Http,Request,我正在处理遗留代码,需要做一个补丁 问题是:一个古老的应用程序发送错误的HTTP POST请求。其中一个参数不是URL编码的。我知道这个参数总是最后一个,我知道它的名字。我现在尝试在tomcat内部运行的服务器端修复它 无法通过HttpServletRequest的标准getParameter方法访问此参数,因为它的格式不正确。方法只返回null。但是当我通过ServletInputStream手动读取整个请求时,所有其他参数都消失了。看起来基础类无法解析ServletInputStream的内

我正在处理遗留代码,需要做一个补丁

问题是:一个古老的应用程序发送错误的HTTP POST请求。其中一个参数不是URL编码的。我知道这个参数总是最后一个,我知道它的名字。我现在尝试在tomcat内部运行的服务器端修复它

无法通过HttpServletRequest的标准getParameter方法访问此参数,因为它的格式不正确。方法只返回null。但是当我通过ServletInputStream手动读取整个请求时,所有其他参数都消失了。看起来基础类无法解析ServletInputStream的内容,因为它已耗尽

到目前为止,我已经成功地制作了一个包装器,它从主体中读取所有参数并覆盖所有参数访问方法。但是,如果在我之前的链中的任何过滤器尝试访问任何参数,那么一切都将中断,因为ServletiInputStream将为空

我能设法回避这个问题吗?可能有不同的方法吗


总之,如果我在过滤器中读取原始请求体,参数将从请求中消失。如果我读取单个参数,ServletInputStream将变为空,无法手动处理。此外,不可能通过getParameter方法读取格式错误的参数。

与其重写方法,不如安装一个重写请求的servlet过滤器


Jason Hunter有一个非常好的方法。

您可以编写自己的Servlet过滤器,并希望确保它出现在链的第一位。然后将ServletRequest对象包装成可以在需要时处理重写的东西。请查看的编程自定义请求和响应部分

------更新------


我一定错过了什么。您说您可以自己读取请求主体和参数。然后你不能确保你的过滤器是第一个,包装ServletRequest对象,读取、处理和存储参数,将你的请求对象传递到链上,并提供你存储的参数而不是原始参数吗?

我找到的解决方案:

仅仅重新定义参数访问方法是不够的。必须做几件事

  • 需要一个过滤器来包装请求
  • 需要一个自定义的HttpRequestWrapper,覆盖所有参数访问方法。请求主体应该在构造函数中解析并存储为字段
  • getInputStreamgetReader方法也应该重新定义。它们返回的值取决于存储的请求主体
  • 自定义类扩展ServletiInputStream是必需的,因为这个类是抽象的
  • 这4个组合将允许您使用getParameter,而不会干扰getInputStreamgetReader方法

    请注意,对于多部分请求,手动请求参数解析可能会变得复杂。但这是另一个话题


    为了澄清,我重新定义了参数访问方法,因为我的请求如问题中所述被破坏了。您可能不需要它。

    我做了一个更完整的包装,允许您在内容类型为application/x-www-form-urlencoded并且您已经调用了其中一个getParameterXXX方法的情况下仍然访问内容:

    import java.io.BufferedReader;
    import java.io.ByteArrayInputStream;
    import java.io.IOException;  
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.UnsupportedEncodingException;
    import java.net.URLDecoder;
    import java.security.Principal;
    import java.util.Enumeration;
    import java.util.HashMap;
    import java.util.LinkedList;
    import java.util.Locale;
    import java.util.Map;
    import java.util.StringTokenizer;
    
    import javax.servlet.RequestDispatcher;
    import javax.servlet.ServletInputStream;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpSession;
    
    /**
     * This class implements the Wrapper or Decorator pattern.<br/> 
     * Methods default to calling through to the wrapped request object, 
     * except the ones that read the request's content (parameters, stream or reader).
     * <p>
     * This class provides a buffered content reading that allows the methods
     * {@link #getReader()}, {@link #getInputStream()} and any of the getParameterXXX to be     called
     * safely and repeatedly with the same results.
     * <p>
     * This class is intended to wrap relatively small HttpServletRequest instances.
     * 
     * @author pgurov
     */
    public class HttpServletRequestWrapper implements HttpServletRequest {
    
    private class ServletInputStreamWrapper extends ServletInputStream {
    
        private byte[] data;
        private int idx = 0;
        ServletInputStreamWrapper(byte[] data) {
            if(data == null)
                data = new byte[0];
            this.data = data;
        }
        @Override
        public int read() throws IOException {
            if(idx == data.length)
                return -1;
            return data[idx++];
        }
    
    }
    
    private HttpServletRequest req;
    private byte[] contentData;
    private HashMap<String, String[]> parameters;
    
    public HttpServletRequestWrapper() {
        //a trick for Groovy
        throw new IllegalArgumentException("Please use HttpServletRequestWrapper(HttpServletRequest request) constructor!");
    }
    
    private HttpServletRequestWrapper(HttpServletRequest request, byte[] contentData, HashMap<String, String[]> parameters) {
        req = request;
        this.contentData = contentData;
        this.parameters = parameters;
    }
    
    public HttpServletRequestWrapper(HttpServletRequest request) {
        if(request == null)
            throw new IllegalArgumentException("The HttpServletRequest is null!");
        req = request;
    }
    
    /**
     * Returns the wrapped HttpServletRequest.
     * Using the getParameterXXX(), getInputStream() or getReader() methods may interfere
     * with this class operation.
     * 
     * @return 
     *      The wrapped HttpServletRequest.
     */
    public HttpServletRequest getRequest() {
        try {
            parseRequest();
        } catch (IOException e) {
            throw new IllegalStateException("Cannot parse the request!", e);
        }
        return new HttpServletRequestWrapper(req, contentData, parameters);
    }
    
    /**
     * This method is safe to use multiple times.
     * Changing the returned array will not interfere with this class operation.
     * 
     * @return 
     *      The cloned content data.
     */
    public byte[] getContentData() {
        return contentData.clone();
    }
    
    /**
     * This method is safe to use multiple times.
     * Changing the returned map or the array of any of the map's values will not
     * interfere with this class operation.
     * 
     * @return
     *      The clonned parameters map.
     */
    public HashMap<String, String[]> getParameters() {
        HashMap<String, String[]> map = new HashMap<String, String[]>(parameters.size() * 2);
        for(String key : parameters.keySet()) {
            map.put(key, parameters.get(key).clone());
        }
        return map;
    }
    
    private void parseRequest() throws IOException {
        if(contentData != null)
            return; //already parsed
    
        byte[] data = new byte[req.getContentLength()];
        int len = 0, totalLen = 0;
        InputStream is = req.getInputStream();
        while(totalLen < data.length) {
            totalLen += (len = is.read(data, totalLen, data.length - totalLen));
            if(len < 1)
                throw new IOException("Cannot read more than " + totalLen + (totalLen == 1 ? " byte!" : " bytes!"));
        }
        contentData = data;
        String enc = req.getCharacterEncoding();
        if(enc == null)
            enc = "UTF-8";
        String s = new String(data, enc), name, value;
        StringTokenizer st = new StringTokenizer(s, "&");
        int i;
        HashMap<String, LinkedList<String>> mapA = new HashMap<String, LinkedList<String>>(data.length * 2);
        LinkedList<String> list;
        boolean decode = req.getContentType() != null && req.getContentType().equals("application/x-www-form-urlencoded");
        while(st.hasMoreTokens()) {
            s = st.nextToken();
            i = s.indexOf("=");
            if(i > 0 && s.length() > i + 1) {
                name = s.substring(0, i);
                value = s.substring(i+1);
                if(decode) {
                    try {
                        name = URLDecoder.decode(name, "UTF-8");
                    } catch(Exception e) {}
                    try {
                        value = URLDecoder.decode(value, "UTF-8");
                    } catch(Exception e) {}
                }
                list = mapA.get(name);
                if(list == null) {
                    list = new LinkedList<String>();
                    mapA.put(name, list);
                }
                list.add(value);
            }
        }
        HashMap<String, String[]> map = new HashMap<String, String[]>(mapA.size() * 2);
        for(String key : mapA.keySet()) {
            list = mapA.get(key);
            map.put(key, list.toArray(new String[list.size()]));
        }
        parameters = map;
    }
    
    /**
     * This method is safe to call multiple times.
     * Calling it will not interfere with getParameterXXX() or getReader().
     * Every time a new ServletInputStream is returned that reads data from the begining.
     * 
     * @return
     *      A new ServletInputStream.
     */
    public ServletInputStream getInputStream() throws IOException {
        parseRequest();
    
        return new ServletInputStreamWrapper(contentData);
    }
    
    /**
     * This method is safe to call multiple times.
     * Calling it will not interfere with getParameterXXX() or getInputStream().
     * Every time a new BufferedReader is returned that reads data from the begining.
     * 
     * @return
     *      A new BufferedReader with the wrapped request's character encoding (or UTF-8 if null).
     */
    public BufferedReader getReader() throws IOException {
        parseRequest();
    
        String enc = req.getCharacterEncoding();
        if(enc == null)
            enc = "UTF-8";
        return new BufferedReader(new InputStreamReader(new ByteArrayInputStream(contentData), enc));
    }
    
    /**
     * This method is safe to execute multiple times.
     * 
     * @see javax.servlet.ServletRequest#getParameter(java.lang.String)
     */
    public String getParameter(String name) {
        try {
            parseRequest();
        } catch (IOException e) {
            throw new IllegalStateException("Cannot parse the request!", e);
        }
        String[] values = parameters.get(name);
        if(values == null || values.length == 0)
            return null;
        return values[0];
    }
    
    /**
     * This method is safe.
     * 
     * @see {@link #getParameters()}
     * @see javax.servlet.ServletRequest#getParameterMap()
     */
    @SuppressWarnings("unchecked")
    public Map getParameterMap() {
        try {
            parseRequest();
        } catch (IOException e) {
            throw new IllegalStateException("Cannot parse the request!", e);
        }
        return getParameters();
    }
    
    /**
     * This method is safe to execute multiple times.
     * 
     * @see javax.servlet.ServletRequest#getParameterNames()
     */
    @SuppressWarnings("unchecked")
    public Enumeration getParameterNames() {
        try {
            parseRequest();
        } catch (IOException e) {
            throw new IllegalStateException("Cannot parse the request!", e);
        }
        return new Enumeration<String>() {
            private String[] arr = getParameters().keySet().toArray(new String[0]); 
            private int idx = 0;
    
            public boolean hasMoreElements() {
                return idx < arr.length;
            }
    
            public String nextElement() {
                return arr[idx++];
            }
    
        };
    }
    
    /**
     * This method is safe to execute multiple times.
     * Changing the returned array will not interfere with this class operation.
     * 
     * @see javax.servlet.ServletRequest#getParameterValues(java.lang.String)
     */
    public String[] getParameterValues(String name) {
        try {
            parseRequest();
        } catch (IOException e) {
            throw new IllegalStateException("Cannot parse the request!", e);
        }
        String[] arr = parameters.get(name);
        if(arr == null)
            return null;
        return arr.clone();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.http.HttpServletRequest#getAuthType()
     */
    public String getAuthType() {
        return req.getAuthType();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.http.HttpServletRequest#getContextPath()
     */
    public String getContextPath() {
        return req.getContextPath();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.http.HttpServletRequest#getCookies()
     */
    public Cookie[] getCookies() {
        return req.getCookies();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.http.HttpServletRequest#getDateHeader(java.lang.String)
     */
    public long getDateHeader(String name) {
        return req.getDateHeader(name);
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.http.HttpServletRequest#getHeader(java.lang.String)
     */
    public String getHeader(String name) {
        return req.getHeader(name);
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.http.HttpServletRequest#getHeaderNames()
     */
    @SuppressWarnings("unchecked")
    public Enumeration getHeaderNames() {
        return req.getHeaderNames();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.http.HttpServletRequest#getHeaders(java.lang.String)
     */
    @SuppressWarnings("unchecked")
    public Enumeration getHeaders(String name) {
        return req.getHeaders(name);
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.http.HttpServletRequest#getIntHeader(java.lang.String)
     */
    public int getIntHeader(String name) {
        return req.getIntHeader(name);
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.http.HttpServletRequest#getMethod()
     */
    public String getMethod() {
        return req.getMethod();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.http.HttpServletRequest#getPathInfo()
     */
    public String getPathInfo() {
        return req.getPathInfo();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.http.HttpServletRequest#getPathTranslated()
     */
    public String getPathTranslated() {
        return req.getPathTranslated();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.http.HttpServletRequest#getQueryString()
     */
    public String getQueryString() {
        return req.getQueryString();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.http.HttpServletRequest#getRemoteUser()
     */
    public String getRemoteUser() {
        return req.getRemoteUser();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.http.HttpServletRequest#getRequestURI()
     */
    public String getRequestURI() {
        return req.getRequestURI();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.http.HttpServletRequest#getRequestURL()
     */
    public StringBuffer getRequestURL() {
        return req.getRequestURL();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.http.HttpServletRequest#getRequestedSessionId()
     */
    public String getRequestedSessionId() {
        return req.getRequestedSessionId();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.http.HttpServletRequest#getServletPath()
     */
    public String getServletPath() {
        return req.getServletPath();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.http.HttpServletRequest#getSession()
     */
    public HttpSession getSession() {
        return req.getSession();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.http.HttpServletRequest#getSession(boolean)
     */
    public HttpSession getSession(boolean create) {
        return req.getSession(create);
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.http.HttpServletRequest#getUserPrincipal()
     */
    public Principal getUserPrincipal() {
        return req.getUserPrincipal();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromCookie()
     */
    public boolean isRequestedSessionIdFromCookie() {
        return req.isRequestedSessionIdFromCookie();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromURL()
     */
    public boolean isRequestedSessionIdFromURL() {
        return req.isRequestedSessionIdFromURL();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromUrl()
     */
    @SuppressWarnings("deprecation")
    public boolean isRequestedSessionIdFromUrl() {
        return req.isRequestedSessionIdFromUrl();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdValid()
     */
    public boolean isRequestedSessionIdValid() {
        return req.isRequestedSessionIdValid();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.http.HttpServletRequest#isUserInRole(java.lang.String)
     */
    public boolean isUserInRole(String role) {
        return req.isUserInRole(role);
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.ServletRequest#getAttribute(java.lang.String)
     */
    public Object getAttribute(String name) {
        return req.getAttribute(name);
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.ServletRequest#getAttributeNames()
     */
    @SuppressWarnings("unchecked")
    public Enumeration getAttributeNames() {
        return req.getAttributeNames();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.ServletRequest#getCharacterEncoding()
     */
    public String getCharacterEncoding() {
        return req.getCharacterEncoding();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.ServletRequest#getContentLength()
     */
    public int getContentLength() {
        return req.getContentLength();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.ServletRequest#getContentType()
     */
    public String getContentType() {
        return req.getContentType();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.ServletRequest#getLocalAddr()
     */
    public String getLocalAddr() {
        return req.getLocalAddr();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.ServletRequest#getLocalName()
     */
    public String getLocalName() {
        return req.getLocalName();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.ServletRequest#getLocalPort()
     */
    public int getLocalPort() {
        return req.getLocalPort();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.ServletRequest#getLocale()
     */
    public Locale getLocale() {
        return req.getLocale();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.ServletRequest#getLocales()
     */
    @SuppressWarnings("unchecked")
    public Enumeration getLocales() {
        return req.getLocales();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.ServletRequest#getProtocol()
     */
    public String getProtocol() {
        return req.getProtocol();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.ServletRequest#getRealPath(java.lang.String)
     */
    @SuppressWarnings("deprecation")
    public String getRealPath(String path) {
        return req.getRealPath(path);
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.ServletRequest#getRemoteAddr()
     */
    public String getRemoteAddr() {
        return req.getRemoteAddr();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.ServletRequest#getRemoteHost()
     */
    public String getRemoteHost() {
        return req.getRemoteHost();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.ServletRequest#getRemotePort()
     */
    public int getRemotePort() {
        return req.getRemotePort();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.ServletRequest#getRequestDispatcher(java.lang.String)
     */
    public RequestDispatcher getRequestDispatcher(String path) {
        return req.getRequestDispatcher(path);
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.ServletRequest#getScheme()
     */
    public String getScheme() {
        return req.getScheme();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.ServletRequest#getServerName()
     */
    public String getServerName() {
        return req.getServerName();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.ServletRequest#getServerPort()
     */
    public int getServerPort() {
        return req.getServerPort();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.ServletRequest#isSecure()
     */
    public boolean isSecure() {
        return req.isSecure();
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.ServletRequest#removeAttribute(java.lang.String)
     */
    public void removeAttribute(String name) {
        req.removeAttribute(name);
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.ServletRequest#setAttribute(java.lang.String, java.lang.Object)
     */
    public void setAttribute(String name, Object value) {
        req.setAttribute(name, value);
    }
    
    /* (non-Javadoc)
     * @see javax.servlet.ServletRequest#setCharacterEncoding(java.lang.String)
     */
    public void setCharacterEncoding(String env)
            throws UnsupportedEncodingException {
        req.setCharacterEncoding(env);
    }
    
    }
    
    导入java.io.BufferedReader;
    导入java.io.ByteArrayInputStream;
    导入java.io.IOException;
    导入java.io.InputStream;
    导入java.io.InputStreamReader;
    导入java.io.UnsupportedEncodingException;
    导入java.net.url解码器;
    导入java.security.Principal;
    导入java.util.Enumeration;
    导入java.util.HashMap;
    导入java.util.LinkedList;
    导入java.util.Locale;
    导入java.util.Map;
    导入java.util.StringTokenizer;
    导入javax.servlet.RequestDispatcher;
    导入javax.servlet.ServletInputStream;
    导入javax.servlet.http.Cookie;
    导入javax.servlet.http.HttpServletRequest;
    导入javax.servlet.http.HttpSession;
    /**
    *此类实现包装器或装饰器模式。
    *方法默认为调用包装的请求对象, *除了那些读取请求内容的(参数、流或读取器)。 * *此类提供了一个缓冲内容读取,允许 *{@link#getReader()}、{@link#getInputStream()}和任何要调用的getParameterXXX *安全且重复,结果相同。 * *此类用于包装相对较小的HttpServletRequest实例。 * *@pgurov */ 公共类HttpServletRequestWrapper实现HttpServletRequest{ 私有类ServletInputStreamWrapper扩展了ServletInputStream{ 专用字节[]数据; 私有整数idx=0; ServletInputStreamWrapper(字节[]数据){ 如果(数据==null) 数据=新字节[0]; 这个数据=数据; } @凌驾 public int read()引发IOException{ if(idx==data.length) 返回-1; 返回数据[idx++]; } } 私有HttpServletRequest请求; 私有字节[]内容数据; 私有HashMap参数; 公共HttpServletRequestWrapper(){ //Groovy的诀窍 抛出新的IllegalArgumentException(“请使用HttpServletRequestWrapper(HttpServletRequest)构造函数!”); } 私有HttpServletRequestWrapper(HttpServletRequest请求,字节[]contentData,HashMap参数){ req=请求; this.contentData=contentData; 此参数=参数; } 公共HttpServletRequestWrapper(HttpServletRequest请求){ if(请求==null) 抛出新的IllegalArgumentException(“HttpServletRequest为null!”); req=请求; } /** *返回包装的HttpServletRequest。 *使用getParameterXXX()、getInputStream()或getReader()方法可能会产生干扰 *用这个类操作。 * *@返回 *包装好的HttpServletRequest。 */ 公共HttpServletRequest getRequest(){
        public int read() throws IOException {
            if (index == data.length) {
                return -1;
            }
            return data[index++] & 0xff;
        }