Используйте фильтр сервлетов, чтобы удалить параметр формы из опубликованных данных.

java servlets servlet-filters

10302 просмотра

2 ответа

41 Репутация автора

Поставщик размещает данные XML через HTTPS в переменной формы с именем XMLContent на моем сервере приложений Coldfusion. Недавно я перешел на более новую версию сервера приложений, и эти запросы выдают 500 ошибок сервера. Он выдает ошибку, потому что содержимое второго параметра формы неправильно закодировано, но этот параметр мне все равно не нужен. (Я связался с продавцом, чтобы исправить это, но они заставляют меня заплатить, чтобы исправить их ошибку, поэтому я стараюсь исправить это сам, если это возможно.)

Как бы я использовал фильтр сервлетов, чтобы удалить все, кроме параметра формы с именем: XMLContent Я пробовал различные попытки явно удалить ошибочный параметр "TContent", но он никогда не удаляется.

Фрагмент полученных данных:

XMLContent=%3C%3Fxml+version%3D%221.0%22+encoding%3D%22UTF-8%22%3F%3E%0A%3CCheck+xmlns%3D%22http .........&TContent=<!--?xml version="1.0" encoding="UTF-8"?--><check xmlns="http...........

Код, который я пробовал:

import java.io.IOException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;


import java.util.*;



public class MultipartFilter implements Filter {

// Init ----------------------------------------------------------------

  public FilterConfig filterConfig;

// Actions -------------------------------------------------------------


public void init(FilterConfig filterConfig) throws ServletException {
    this.filterConfig = filterConfig;
}

/**
 * Check the type request and if it is a HttpServletRequest, then parse the request.
 * @throws ServletException If parsing of the given HttpServletRequest fails.
 * @see javax.servlet.Filter#doFilter(
 *      javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
 */
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
    throws ServletException, IOException
{
    // Check type request.
    if (request instanceof HttpServletRequest) {
        // Cast back to HttpServletRequest.
        HttpServletRequest httpRequest = (HttpServletRequest) request;

        // Parse HttpServletRequest.
        HttpServletRequest parsedRequest = parseRequest(httpRequest);

        // Continue with filter chain.
        chain.doFilter(parsedRequest, response);
    } else {
        // Not a HttpServletRequest.
        chain.doFilter(request, response);
    }
}

/**
 * @see javax.servlet.Filter#destroy()
 */
public void destroy() {
    this.filterConfig = null;
}



private HttpServletRequest parseRequest(HttpServletRequest request) throws ServletException {

    // Prepare the request parameter map.
    Map<String, String[]> parameterMap = new HashMap<String, String[]>();

    // Loop through form parameters.
Enumeration<String> parameterNames = request.getParameterNames();

    while (parameterNames.hasMoreElements()) {
    String paramName = parameterNames.nextElement();
    String[] paramValues = request.getParameterValues(paramName);

            // Add just the XMLContent form parameter
    if (paramName.equalsIgnoreCase("xmlcontent")) {   

        parameterMap.put(paramName, new String[] { paramValues[0] });

    }
}

    // Wrap the request with the parameter map which we just created and return it.
    return wrapRequest(request, parameterMap);
}



// Utility (may be refactored to public utility class) ---------------

/**
 * Wrap the given HttpServletRequest with the given parameterMap.
 * @param request The HttpServletRequest of which the given parameterMap have to be wrapped in.
 * @param parameterMap The parameterMap to be wrapped in the given HttpServletRequest.
 * @return The HttpServletRequest with the parameterMap wrapped in.
 */
private static HttpServletRequest wrapRequest(
    HttpServletRequest request, final Map<String, String[]> parameterMap)
{
    return new HttpServletRequestWrapper(request) {
        public Map<String, String[]> getParameterMap() {
            return parameterMap;
        }
        public String[] getParameterValues(String name) {
            return parameterMap.get(name);
        }
        public String getParameter(String name) {
            String[] params = getParameterValues(name);
            return params != null && params.length > 0 ? params[0] : null;
        }
        public Enumeration<String> getParameterNames() {
            return Collections.enumeration(parameterMap.keySet());
        }
    };
  }
}
Автор: Matt Источник Размещён: 11.07.2013 06:59

Ответы (2)


6 плюса

86 Репутация автора

Мы сталкиваемся с этими ситуациями каждый день, работая с языком. Если языковой стандарт пользователя отличается от языкового стандарта браузера, мы должны обновить запрос. Но это не изменчиво.

Решение: создать класс-оболочку запроса. Скопируйте в него существующие параметры запроса (те, которые вам нужны) и передайте этот класс-оболочку в filterchain.doFilter ()

образец обертки класса:

public class WrappedRequest extends HttpServletRequestWrapper
{
  Map<String, String[]> parameterMap;
  public WrappedRequest(final HttpServletRequest request)
  {
   //build your param Map here with required values
  }

  @Override
  public Map<String, String[]> getParameterMap()
  {
    //return local param map
  }

  //override other methods if needed.

}

Теперь в вашем коде фильтра сделайте следующее.

wrapRequest = new WrappedRequest(hreq);
filterChain.doFilter(wrapRequest, servletResponse);

Надеюсь, это решит вашу проблему.

Автор: ajgautam Размещён: 19.07.2013 10:08

5 плюса

20159 Репутация автора

Подход

Код следует правильному подходу:

  • в wrapRequest(), он создает HttpServletRequestWrapperи переопределяет 4 метода, которые запускают разбор запроса:

    • public String getParameter(String name)
    • public Map<String, String[]> getParameterMap()
    • public Enumeration<String> getParameterNames()
    • public String[] getParameterValues(String name)
  • doFilter()метод вызывает цепочку фильтров , используя обернутый запрос, то есть последующие фильтры, а также целевой сервлет (URL-карта) будет поставляться обернутым запросом.

проблема

  • Вызов любого из 4 методов getParameterXXX () для базового «исходного запроса» запускает неявный синтаксический анализ всех параметров запроса (через внутренний метод сервера, такой как Request.parseRequestParameters or parsePameters). Эти 4 метода - единственный способ вызвать такой анализ.
  • Перед упаковкой запроса parseRequest()ваш код вызывает такие методы для базового запроса:

    request.getParameterNames();
    
    request.getParameterValues(paramName);
    

Решение

Вам нужно контролировать логику разбора. Чтение необработанных байтов из входного потока и выполнение собственного декодирования URL слишком сложно - это будет означать замену большого объема тесно связанного серверного кода. Вместо этого самый простой подход - просто заменить метод, который выполняет фактическое декодирование URL. Это означает, что вы можете оставить на месте request.getParameterXXXзвонки, упомянутые в предыдущем разделе.

Не знаю, на каком сервере вы используете ColdFusion, но приведенное ниже описание основано на Glassfish / Tomcat, но может быть адаптировано. В нижней части этого поста находится метод анализа внутренних запросов от Glassfish (модифицированная версия Tomcat). JD-декомпилятор полезен для этой работы для преобразования файлов .class в .java.

  1. Найти класс , который делает URL для декодирования (Glassfish это com.sun.grizzly.util.http.Parametersот , grizzly-utils.jarкак показано ниже, для Tomcat это org.apache.tomcat.util.http.Parametersс tomcat-coyote.jar)
  2. Скопируйте весь исходный код в новый класс somepackage.StrippedParameters
  3. Найдите строку кода , который декодирует значение параметра (ниже value = urlDecode(this.tmpValue))
  4. Измените этот код так, чтобы он декодировался только тогда, когда имя параметра соответствует желаемому параметру:

    if (decodeName)
      name = urlDecode(this.tmpName);
    else
      name = this.tmpName.toString();
    // 
    // !! THIS IF STATEMENT ADDED TO ONLY DECODE DESIRED PARAMETERS, 
    // !! OTHERS ARE STRIPPED:
    //
    if ("XMLContent".equals(name)) {
        String value;
        String value;
        if (decodeValue)
          value = urlDecode(this.tmpValue);
        else {
          value = this.tmpValue.toString();
        }
        try
        {
          addParameter(name, value);
        }
        catch (IllegalStateException ise)
        {
          logger.warning(ise.getMessage());
          break;
        }
    }
    
  5. Теперь самое сложное: замените класс по умолчанию Parametersвашим классом StrippedParmetersнепосредственно перед декодированием URL. Как только параметры получены, скопируйте их обратно в класс контейнера. Для Glassfish скопируйте метод parseRequestParameters в вашу реализацию HttpServletRequestWrapper (для Tomcat соответствующий метод находится parseParametersв классе org.apache.catalina.connector.Requestin catalina.jar)

    • замените эту строку:

      Parameters parameters = this.coyoteRequest.getParameters();
      

      с участием:

      Parameters parameters = new somepackage.StrippedParameters();
      
    • в нижней части метода добавьте это:

      Parameters coyoteParameters = this.coyoteRequest.getParameters();
      for (String paramName : parameters.getParameterNames()) {
          String paramValue = parameters.getParameterValue(paramName);
          coyoteParameters.addParameter(paramName, paramValue);
      }
      

Код контейнера Glassfish - модифицированная версия Tomcat, в которой Grizzly заменяет Coyote (Servlet Engine от Catalina по-прежнему ссылается на объекты Coyote, но это экземпляры Grizzly, издевающиеся над Coyote)

package org.apache.catalina.connector;
....
public class Request  implements HttpRequest, HttpServletRequest {
    ....
    protected com.sun.grizzly.tcp.Request coyoteRequest;
    ....    
    // This is called from the 4 methods named 'getParameterXXX'
    protected void parseRequestParameters()  {
        Parameters parameters = this.coyoteRequest.getParameters();
        parameters.setLimit(getConnector().getMaxParameterCount());
        String enc = getCharacterEncoding();
        this.requestParametersParsed = true;
        if (enc != null) {
            parameters.setEncoding(enc);
            parameters.setQueryStringEncoding(enc);
        } else {
            parameters.setEncoding("ISO-8859-1");
            parameters.setQueryStringEncoding("ISO-8859-1");
        }
        parameters.handleQueryParameters();
        if ((this.usingInputStream) || (this.usingReader)) {
            return;
        }
        if (!getMethod().equalsIgnoreCase("POST")) {
            return;
        }
        String contentType = getContentType();
        if (contentType == null) {
            contentType = "";
        }
        int semicolon = contentType.indexOf(';');
        if (semicolon >= 0)
            contentType = contentType.substring(0, semicolon).trim();
        else {
            contentType = contentType.trim();
        }
        if ((isMultipartConfigured()) && ("multipart/form-data".equals(contentType)))  {
            getMultipart().init();
        }
        if (!"application/x-www-form-urlencoded".equals(contentType)) {
            return;
        }
        int len = getContentLength();
        if (len > 0) {
        int maxPostSize = ((Connector)this.connector).getMaxPostSize();
        if ((maxPostSize > 0) && (len > maxPostSize)) {
            log(sm.getString("coyoteRequest.postTooLarge"));
            throw new IllegalStateException("Post too large");
        }
        try {
            byte[] formData = getPostBody();
            if (formData != null)
                parameters.processParameters(formData, 0, len);
        } catch (Throwable t) {
        }
    }
  }
}

package com.sun.grizzly.tcp;

import com.sun.grizzly.util.http.Parameters;
public class Request {
    ....
    private Parameters parameters = new Parameters();
    ....
    public Parameters getParameters() {
        return this.parameters;
    }
}

package com.sun.grizzly.util.http;

public class Parameters {
    ....
    public void processParameters(byte[] bytes, int start, int len) {
        processParameters(bytes, start, len, getCharset(this.encoding));
    }

    public void processParameters(byte[] bytes, int start, int len, Charset charset) {
        if (debug > 0) {
        try {
            log(sm.getString("parameters.bytes", new String(bytes, start, len, "ISO-8859-1")));
        } catch (UnsupportedEncodingException e) {
            logger.log(Level.SEVERE, sm.getString("parameters.convertBytesFail"), e);
        }
    }
    int decodeFailCount = 0;
    int end = start + len;
    int pos = start;
    while (pos < end) {
        int nameStart = pos;
        int nameEnd = -1;
        int valueStart = -1;
        int valueEnd = -1;
        boolean parsingName = true;
        boolean decodeName = false;
        boolean decodeValue = false;
        boolean parameterComplete = false;
        do {
            switch (bytes[pos]) {
              case 61:
                  if (parsingName) {
                      nameEnd = pos;
                      parsingName = false;
                      pos++; valueStart = pos;
                  } else {
                      pos++;
                  }
                  break;
              case 38:
                  if (parsingName) {
                      nameEnd = pos;
                  } else {
                      valueEnd = pos;
                  }
                  parameterComplete = true;
                  pos++;
                  break;
              case 37:
              case 43:
                  if (parsingName)
                      decodeName = true;
                  else {
                      decodeValue = true;
                  }
                  pos++;
                  break;
              default:
                  pos++;
            }
        } while ((!parameterComplete) && (pos < end));
        if (pos == end) {
            if (nameEnd == -1)
                nameEnd = pos;
            else if ((valueStart > -1) && (valueEnd == -1)) {
                valueEnd = pos;
            }
        }
        if ((debug > 0) && (valueStart == -1)) {
            try {
                log(sm.getString("parameters.noequal", Integer.valueOf(nameStart),
                Integer.valueOf(nameEnd), 
                new String(bytes, nameStart, nameEnd - nameStart, "ISO-8859-1")));
            } catch (UnsupportedEncodingException e) {
                logger.log(Level.SEVERE, sm.getString("parameters.convertBytesFail"), e);
            }
        }

        if (nameEnd <= nameStart) {
            if (logger.isLoggable(Level.INFO)) {
                if (valueEnd >= nameStart)
                    try {
                        new String(bytes, nameStart, valueEnd - nameStart, "ISO-8859-1");
                    } catch (UnsupportedEncodingException e) {
                        logger.log(Level.SEVERE,
                                   sm.getString("parameters.convertBytesFail"), e);
                    } else {
                        logger.fine(sm.getString("parameters.invalidChunk", 
                                Integer.valueOf(nameStart), Integer.valueOf(nameEnd), null));
                    }
                }
            } else {
                this.tmpName.setCharset(charset);
                this.tmpValue.setCharset(charset);
                this.tmpName.setBytes(bytes, nameStart, nameEnd - nameStart);
                this.tmpValue.setBytes(bytes, valueStart, valueEnd - valueStart);
    if (debug > 0)
      try {
        this.origName.append(bytes, nameStart, nameEnd - nameStart);
        this.origValue.append(bytes, valueStart, valueEnd - valueStart);
      }
      catch (IOException ioe) {
        logger.log(Level.SEVERE, sm.getString("parameters.copyFail"), ioe);
      }
    try
    {
      String name;
      String name;
      if (decodeName)
        name = urlDecode(this.tmpName);
      else
        name = this.tmpName.toString();
      String value;
      String value;
      if (decodeValue)
        value = urlDecode(this.tmpValue);
      else {
        value = this.tmpValue.toString();
      }
      try
      {
        addParameter(name, value);
      }
      catch (IllegalStateException ise)
      {
        logger.warning(ise.getMessage());
        break;
      }
    } catch (IOException e) {
      decodeFailCount++;
      if ((decodeFailCount == 1) || (debug > 0)) {
        if (debug > 0) {
          log(sm.getString("parameters.decodeFail.debug", this.origName.toString(), this.origValue.toString()), e);
        }
        else if (logger.isLoggable(Level.INFO)) {
          logger.log(Level.INFO, sm.getString("parameters.decodeFail.info", this.tmpName.toString(), this.tmpValue.toString()), e);
        }
      }

    }

    this.tmpName.recycle();
    this.tmpValue.recycle();

    if (debug > 0) {
      this.origName.recycle();
      this.origValue.recycle();
    }
  }
}
if ((decodeFailCount > 1) && (debug <= 0))
  logger.info(sm.getString("parameters.multipleDecodingFail", Integer.valueOf(decodeFailCount)));

}

Автор: Glen Best Размещён: 23.07.2013 07:40
Вопросы из категории :
32x32