Перейти к основному содержимому

Обзор и необходимость DelegatingFilterProxy в Spring

· 4 мин. чтения

1. Обзор

DelegatingFilterProxy — это фильтр сервлета, который позволяет передавать управление классам Filter , имеющим доступ к контексту приложения Spring. Spring Security сильно зависит от этой техники.

В этом уроке мы подробно расскажем об этом.

2. ДелегированиеFilterProxy

В Javadoc для DelegatingFilterProxy указано, что это

Прокси для стандартного фильтра сервлетов, делегирующий управление bean-компоненту Spring, который реализует интерфейс фильтра.

При использовании фильтров сервлетов нам, очевидно, необходимо объявить их как фильтр-класс в нашем Java-config или web.xml , иначе контейнер сервлета их проигнорирует. Spring DelegatingFilterProxy обеспечивает связь между web.xml и контекстом приложения.

2.1. Внутренняя работа DelegatingFilterProxy

Давайте посмотрим, как DelegatingFilterProxy передает управление нашему bean-компоненту Spring.

Во время инициализации DelegatingFilterProxy извлекает имя фильтра и извлекает bean-компонент с этим именем из Spring Application Context. Этот bean-компонент должен иметь тип javax.Servlet.Filter, то есть «обычный» фильтр сервлета. Затем входящие запросы будут передаваться этому фильтрующему компоненту.

Короче говоря, метод doFilter() DelegatingFilterProxy делегирует все вызовы компоненту Spring, что позволяет нам использовать все функции Spring в нашем компоненте фильтра. ``

Если мы используем конфигурацию на основе Java, наша регистрация фильтра в ApplicationInitializer будет определена как:

@Override
protected javax.servlet.Filter[] getServletFilters() {
DelegatingFilterProxy delegateFilterProxy = new DelegatingFilterProxy();
delegateFilterProxy.setTargetBeanName("applicationFilter");
  return new Filter[]{delegateFilterProxy};
}

Если мы используем XML, то в файле web.xml :

<filter>
<filter-name>applicationFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

Это означает, что любой запрос может пройти через фильтр, определенный как компонент Spring с именем applicationFilter .

2.2. Необходимость делегированияFilterProxy

DelegatingFilterProxy — это класс в веб-модуле Spring. Он предоставляет функции для прохождения HTTP-вызовов через фильтры перед достижением фактического места назначения. С помощью DelegatingFilterProxy класс, реализующий интерфейс javax.Servlet.Filter , может быть подключен к цепочке фильтров.

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

DelegatingFilterProxy также использует вызов определенных или нескольких фильтров в соответствии с путями URI запроса, предоставляя конфигурацию в контексте приложения Spring или в файле web.xml.

3. Создание пользовательского фильтра

Как описано выше, DelegatingFilterProxy сам по себе является фильтром сервлета, который делегирует определенный компонент, управляемый Spring, который реализует интерфейс фильтра .

В следующих нескольких разделах мы создадим собственный фильтр и настроим его с помощью конфигурации на основе Java и XML.

3.1. Класс фильтра

Мы собираемся создать простой фильтр, который регистрирует информацию о запросе до того, как запрос продолжится.

Давайте сначала создадим собственный класс фильтра:

@Component("loggingFilter")
public class CustomFilter implements Filter {

private static Logger LOGGER = LoggerFactory.getLogger(CustomFilter.class);

@Override
public void init(FilterConfig config) throws ServletException {
       // initialize something
}

@Override
public void doFilter(
ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {

HttpServletRequest req = (HttpServletRequest) request;
LOGGER.info("Request Info : " + req);
chain.doFilter(request, response);
}

@Override
public void destroy() {
// cleanup code, if necessary
}
}

CustomFilter реализует javax.Servlet.Filter . Этот класс имеет аннотацию @Component для регистрации в качестве компонента Spring в контексте приложения. Таким образом, класс DelegatingFilterProxy может найти наш класс фильтра при инициализации цепочки фильтров.

Обратите внимание, что имя bean-компонента Spring должно совпадать со значением в имени фильтра, предоставленным во время регистрации пользовательского фильтра в классе ApplicationInitializer или в web.xml позже , потому что класс DelegatingFilterProxy будет искать bean-компонент фильтра с точным одно и то же имя в контексте приложения.

Если он не может найти bean-компонент с таким именем, он вызовет исключение при запуске приложения.

3.2. Настройка фильтра с помощью конфигурации Java

Чтобы зарегистрировать пользовательский фильтр с использованием конфигурации Java, нам нужно переопределить метод getServletFilters() класса AbstractAnnotationConfigDispatcherServletInitializer :

public class ApplicationInitializer 
extends AbstractAnnotationConfigDispatcherServletInitializer {
// some other methods here

@Override
protected javax.servlet.Filter[] getServletFilters() {
DelegatingFilterProxy delegateFilterProxy = new DelegatingFilterProxy();
delegateFilterProxy.setTargetBeanName("loggingFilter");
  return new Filter[]{delegateFilterProxy};
}
}

3.3. Настройка фильтра через web.xml

Давайте посмотрим, как выглядит конфигурация фильтра в web.xml :

<filter>
<filter-name>loggingFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>loggingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

Аргумент класса фильтра относится к типу DelegatingFilterProxy , а не к созданному нами классу фильтра. Если мы запустим этот код и нажмем любой URL-адрес, тогда будет выполнен метод doFilter() CustomFilter и отобразит информацию о запросе в файле журнала.

4. Вывод

В этой статье мы рассмотрели, как работает DelegatingFilterProxy и как его использовать.

Spring Security широко использует DelegatingFilterProxy для защиты вызовов и ресурсов веб-API от несанкционированного доступа.

Исходный код доступен на GitHub .