2009-03-25 30 views
8

Tôi đang làm việc trên mã cũ và cần tạo một bản vá.Sửa đổi phần thân HttpServletRequest

Sự cố: ứng dụng cũ gửi yêu cầu HTTP POST xấu. Một trong các tham số không phải là URL được mã hóa. Tôi biết rằng tham số này luôn luôn đến cuối cùng và tôi biết tên của nó. Tôi đang cố sửa nó ở phía máy chủ đang chạy bên trong tomcat.

Thông số này không thể truy cập thông qua phương thức getParameter chuẩn của HttpServletRequest, vì nó không đúng định dạng. Phương thức đơn giản trả về null. Nhưng khi tôi đọc toàn bộ phần thân yêu cầu thông qua ServletInputStream thì tất cả các tham số khác biến mất. Có vẻ như các lớp cơ bản không thể phân tích cú pháp nội dung của ServletInputStream kể từ khi nó thoát ra ngoài.

Cho đến nay tôi đã quản lý để tạo một trình bao bọc đọc tất cả các tham số từ nội dung và ghi đè tất cả các phương thức truy cập thông số. Nhưng nếu bất kỳ bộ lọc nào trong chuỗi trước khi tôi sẽ cố gắng truy cập vào bất kỳ tham số nào, mọi thứ sẽ bị phá vỡ vì ServletInputStream sẽ trống.

Tôi có thể tránh được vấn đề này bằng cách nào đó không? Có thể có cách tiếp cận khác không?

Để tóm tắt, Nếu tôi đọc phần thân yêu cầu thô trong bộ lọc, các tham số sẽ biến mất khỏi yêu cầu. Nếu tôi đọc tham số đơn, ServletInputStream sẽ trở thành rỗng và xử lý thủ công sẽ là không thể. Hơn nữa, không thể đọc tham số không đúng định dạng thông qua phương thức getParameter.

Trả lời

9

Giải pháp tôi đã tìm thấy:

Nó không đủ để chỉ xác định lại phương pháp tham số truy cập. Một số điều phải được thực hiện.

  1. Cần có bộ lọc khi yêu cầu sẽ được bao bọc.
  2. Tùy chỉnh HttpRequestWrapper là cần thiết với tất cả các phương thức truy cập tham số được ghi đè. Yêu cầu nội dung nên được phân tích cú pháp trong hàm tạo và được lưu trữ dưới dạng một trường.
  3. phương thức getInputStreamgetReader cũng phải được định nghĩa lại. Chúng trả về các giá trị phụ thuộc vào phần thân yêu cầu được lưu trữ.
  4. Mở rộng lớp tùy chỉnh ServletInputStream là bắt buộc vì lớp này trừu tượng.

4 này kết hợp sẽ cho phép bạn sử dụng getParameter mà không cần sự can thiệp với getInputStreamgetReader phương pháp.

Hãy nhớ rằng phân tích cú pháp thông số yêu cầu thủ công có thể phức tạp với yêu cầu nhiều phần. Nhưng đó là một chủ đề khác.

Để làm rõ, tôi đã xác định lại phương thức truy cập tham số vì yêu cầu của tôi đã bị hỏng như được nêu trong câu hỏi. Bạn có thể không cần điều đó.

+0

Bạn có thể vui lòng cung cấp thêm chi tiết về phân tích cú pháp thông số yêu cầu thủ công không? Không đủ để chỉ ghi đè getInputStream và getReader? –

+0

Ok, tôi đã tra cứu. Tôi đã phải phân tích cú pháp các thông số bởi vì một trong số chúng đã bị hỏng như mô tả trong một câu hỏi. Nếu họ được yêu cầu của bạn tốt, không cần phải làm điều đó. – clorz

+2

Xem tại đây để thực hiện đầy đủ: http://stackoverflow.com/a/1048123/535203 –

8

Thay vì các phương pháp ghi đè, tại sao bạn không cài đặt bộ lọc servlet ghi đè yêu cầu?

Jason Hunter có khá tốt article on filters.

1

Bạn có thể viết Bộ lọc Servlet của riêng mình và hy vọng rằng nó sẽ xuất hiện đầu tiên trong chuỗi. Sau đó bọc đối tượng ServletRequest vào thứ gì đó sẽ xử lý việc viết lại khi cần. Có một cái nhìn tại Lập trình tùy chỉnh yêu cầu và phản hồi phần của http://java.sun.com/products/servlet/Filters.html

------ Cập nhật ------

tôi phải mất một cái gì đó. Bạn nói rằng bạn có thể đọc phần thân yêu cầu và tự mình đọc các thông số. Sau đó, bạn có thể đảm bảo bộ lọc của mình được đầu tiên không, bọc đối tượng ServletRequest, đọc, xử lý và lưu trữ các tham số, chuyển đối tượng yêu cầu của bạn lên chuỗi và cung cấp các thông số bạn đã lưu thay vì các tham số gốc?

+0

Tôi có thể đọc tất cả các tham số ngoại trừ thông số bị hỏng. Tôi chỉ có thể đọc tham số bị hỏng thông qua ServletInputStream. Khi tôi sử dụng luồng đầu vào, tất cả các thông số khác sẽ biến mất. Nếu tôi phân tích cú pháp tất cả các tham số từ luồng đầu vào, đôi khi các servlet sẽ bị ngắt chuỗi sau đó. Nó phức tạp =) – clorz

5

Tôi đã làm một wrapper hoàn chỉnh hơn cho phép bạn vẫn truy cập nội dung trong trường hợp Content-Type là application/x-www-form-urlencoded và bạn đã gọi là một trong những phương pháp 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); 
} 

} 
+0

Tại sao bạn cần ghi đè lên tất cả các phương thức được ủy quyền để req đối tượng khi lớp cơ sở đã làm điều đó? – Divick

+0

Tôi nhận ra rằng bạn thực hiện HttpServletRequest thay vì mở rộng HttpServletRequestWrapper do đó bạn cần phải thực hiện tất cả các phương thức cần thiết. Nhưng tại sao không mở rộng từ HttpServletRequestWrapper mà anyways đại biểu các cuộc gọi đến đối tượng yêu cầu ban đầu? – Divick

+0

Phương thức getParameterValues, getParameter dựa trên luồng ban đầu, vì vậy trình bao bọc sẽ không thực hiện. Nhưng tôi cede để sử dụng wrapper để tránh thực hiện tất cả các phương pháp của dòng. Trong thực tế cam kết sẽ từ chối này mà không cần thêm cấu hình độc lập. –

3

Tôi muốn đăng bài này làm bình luận, nhưng tôi không có đủ đại diện. Giải pháp của bạn không đủ trong ServletInputStreamWrapper sẽ trả về số nguyên âm. Ví dụ, giả lập một yêu cầu với mã hóa đầu vào UTF-16, hoặc lớn hoặc nhỏ endian. Dữ liệu đầu vào có thể bắt đầu bằng Dấu đơn hàng Byte cho biết endianess, và khi kiểm tra câu lệnh của tôi, hãy xây dựng nội dung yêu cầu mô phỏng để làm như vậy. http://en.wikipedia.org/wiki/Byte_order_mark#UTF-16 Một trong các BOM này chứa byte 0xFF. Kể từ khi java không có byte unsigned, 0xFF này được trả về như là -1. Để giải quyết vấn đề này, chỉ cần thay đổi chức năng đọc như vậy

public int read() throws IOException { 
     if (index == data.length) { 
      return -1; 
     } 
     return data[index++] & 0xff; 
    } 

Tôi hơi thích giải pháp của bạn vì nó hoạt động tốt với Spring. Lúc đầu, tôi đã cố gắng loại bỏ một số mã ủy quyền bạn đã viết bằng cách mở rộng từ HttpServletRequestWrapper. Tuy nhiên, Spring thực hiện điều gì đó thú vị: khi nó gặp một yêu cầu kiểu ServletRequestWrapper, nó sẽ unwraps nó, gọi getRequest(). Vấn đề là phương thức getRequest() của tôi, như được sao chép từ mã của bạn, trả về một lớp mới mở rộng từ HttpServletRequestWrapper ... rửa sạch và lặp lại vô hạn. Vì vậy, nó buồn để nói, phấn lên một chiến thắng cho không sử dụng giao diện!

+0

Tôi cũng thấy một vấn đề khác, nơi req.getContentType(). Equals ("application/x-www-form-urlencoded") nên req.getContentType(). StartsWith ("application/x-www -form-urlencoded ") Khi nó bật ra, Firefox có thể gửi" application/x-www-form-urlencoded; charset = UTF-8 "trong khi Chrome và IE chỉ gửi" application/x-www-form-urlencoded " – DanielKWinsor

Các vấn đề liên quan