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 .