Используйте фильтр сервлетов, чтобы удалить параметр формы из опубликованных данных.
10302 просмотра
2 ответа
Поставщик размещает данные 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
Источник
Размещён: 12.11.2019 09:52
Ответы (2)
6 плюса
Мы сталкиваемся с этими ситуациями каждый день, работая с языком. Если языковой стандарт пользователя отличается от языкового стандарта браузера, мы должны обновить запрос. Но это не изменчиво.
Решение: создать класс-оболочку запроса. Скопируйте в него существующие параметры запроса (те, которые вам нужны) и передайте этот класс-оболочку в 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:085 плюса
Подход
Код следует правильному подходу:
в
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.
- Найти класс , который делает URL для декодирования (Glassfish это
com.sun.grizzly.util.http.Parameters
от ,grizzly-utils.jar
как показано ниже, для Tomcat этоorg.apache.tomcat.util.http.Parameters
сtomcat-coyote.jar
) - Скопируйте весь исходный код в новый класс
somepackage.StrippedParameters
- Найдите строку кода , который декодирует значение параметра (ниже
value = urlDecode(this.tmpValue)
) Измените этот код так, чтобы он декодировался только тогда, когда имя параметра соответствует желаемому параметру:
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; } }
Теперь самое сложное: замените класс по умолчанию
Parameters
вашим классомStrippedParmeters
непосредственно перед декодированием URL. Как только параметры получены, скопируйте их обратно в класс контейнера. Для Glassfish скопируйте метод parseRequestParameters в вашу реализацию HttpServletRequestWrapper (для Tomcat соответствующий метод находитсяparseParameters
в классеorg.apache.catalina.connector.Request
incatalina.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Вопросы из категории :
- java В чем разница между int и Integer в Java и C #?
- java Как я могу определить IP моего маршрутизатора / шлюза в Java?
- java Каков наилучший способ проверки XML-файла по сравнению с XSD-файлом?
- java Как округлить результат целочисленного деления?
- java Преобразование списка <Integer> в список <String>
- java Почему я не могу объявить статические методы в интерфейсе?
- servlets Сервлет для обслуживания статического контента
- servlets Конструктор сервлетов и метод init ()
- servlets Различия между куки и сессиями?
- servlets Ошибка в скорости и log4J
- servlets Как получить доступ к статическим ресурсам при отображении сервлета глобального фронт-контроллера в / *
- servlets Как перенаправить на страницу входа, когда сеанс истек в веб-приложении Java?
- servlet-filters Аутентификация имени пользователя, пароля с помощью фильтров в Java (связь с базой данных)
- servlet-filters Как использовать фильтр сервлетов в Java для изменения URL-адреса входящего запроса сервлета?
- servlet-filters Использование javax.servlet.Filter с Compojure
- servlet-filters Как читать request.getInputStream () несколько раз
- servlet-filters Глобальный фильтр сервлетов Java, возможно ли это?