Существующее веб-приложение работает на Tomcat 4.1. На странице есть проблема XSS, но я не могу изменить источник. Я решил написать фильтр сервлетов, чтобы очистить параметр до того, как его увидит страница.
Я хотел бы написать такой класс фильтра:
import java.io.*;
import javax.servlet.*;
public final class XssFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
String badValue = request.getParameter("dangerousParamName");
String goodValue = sanitize(badValue);
request.setParameter("dangerousParamName", goodValue);
chain.doFilter(request, response);
}
public void destroy() {
}
public void init(FilterConfig filterConfig) {
}
}
Но ServletRequest.setParameter
не существует.
Как я могу изменить значение параметра запроса перед передачей запроса по цепочке?
java
servlet-filters
Джереми Штайн
источник
источник
Ответы:
Как вы отметили
HttpServletRequest
, не имеет метода setParameter. Это сделано умышленно, поскольку класс представляет запрос в том виде, в каком он пришел от клиента, и изменение параметра не будет отражать этого.Одно из решений - использовать
HttpServletRequestWrapper
класс, который позволяет объединить один запрос с другим. Вы можете создать подкласс и переопределитьgetParameter
метод для возврата вашего очищенного значения. Затем вы можете передать этот завернутый запросchain.doFilter
вместо исходного запроса.Это немного некрасиво, но именно это говорит API сервлетов. Если вы попытаетесь передать что-либо еще
doFilter
, некоторые контейнеры сервлетов будут жаловаться, что вы нарушили спецификацию, и откажутся обрабатывать это.Более элегантное решение - больше работы - измените исходный сервлет / JSP, который обрабатывает параметр, так, чтобы он ожидал атрибут запроса вместо параметра. Фильтр проверяет параметр, очищает его и устанавливает атрибут (using
request.setAttribute
) с очищенным значением. Без подкласса, без спуфинга, но требует изменения других частей вашего приложения.источник
<property name="username" value="somemail@gmail.com" /> //Change email on logging in <property name="password" value="*********" />//Change Password on logging in
Для записи, вот класс, который я написал:
источник
Напишите простой класс, который выполняет субвычисление
HttpServletRequestWrapper
с помощью метода getParameter (), который возвращает очищенную версию ввода. Затем передать экземпляр вашей ,HttpServletRequestWrapper
чтобыFilter.doChain()
вместо объекта запроса напрямую.источник
У меня была такая же проблема (изменение параметра из HTTP-запроса в фильтре). В итоге я использовал файл
ThreadLocal<String>
. УFilter
меня есть:В моем процессоре запросов (
HttpServlet
контроллере JSF или любом другом процессоре HTTP-запросов) я возвращаю текущее значение потока:Преимущества:
HttpServletRequestWrapper
шаблонrequest.setAttribute(String,Object)
, т.е. вы можете получить доступ к переменной в других фильтрах.Недостатки:
java.util.stream.Stream.parallel
,java.util.concurrent.Future
,java.lang.Thread
.Некоторые примечания на стороне:
На сервере есть пул потоков для обработки HTTP-запросов. Поскольку это пул:
if (value!=null) { THREAD_VARIABLE.set(value);}
потому что вы будете повторно использовать значение из предыдущего HTTP-запроса приvalue
нулевом значении: побочные эффекты гарантированы).HttpSession.setAttribute()
@RequestScoped
внутренне использует aThreadLocal
, но его использованиеThreadLocal
более универсально: вы можете использовать его в контейнерах, отличных от JEE / CDI (например, в многопоточных приложениях JRE)источник
@RequestScoped
внутренне делает то же самое). Будет ли несколько запросов видеть один и тот же поток = нет (или, по крайней мере, у вас нет гарантии). Я отредактировал ответ, чтобы уточнить эти моменты.Это то, чем я закончил
источник
Основываясь на всех ваших замечаниях, вот мое предложение, которое сработало для меня:
Примечание: queryString () требует обработки ВСЕХ значений для каждого КЛЮЧА и не забывайте encodeUrl () при добавлении собственных значений параметров, если это необходимо
В качестве ограничения, если вы вызовете request.getParameterMap () или любой метод, который вызовет request.getReader () и начнет чтение, вы предотвратите любые дальнейшие вызовы request.setCharacterEncoding (...)
источник
Вы можете использовать регулярное выражение для очистки. Внутри фильтра перед вызовом метода chain.doFilter (запрос, ответ) вызовите этот код. Вот пример кода:
источник
Попробуй
request.setAttribute("param",value);
. У меня все сработало.Найдите этот пример кода:
источник