В чем смысл DelegatingFilterProxy Spring MVC?


120

Я вижу это в своем приложении Spring MVC web.xml:

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

Я пытаюсь понять, зачем он нужен и действительно ли он нужен.

Я нашел это объяснение в документации Spring, но оно не помогает мне понять его:

Кажется, предполагается, что этот компонент является «связующим звеном» между сервлетами, определенными в, web.xmlи компонентами, определенными в Spring applicationContext.xml.

7.1 ДелегированиеFilterProxy

При использовании фильтров сервлетов вам, очевидно, нужно объявить их в вашем web.xml, иначе они будут проигнорированы контейнером сервлетов. В Spring Security классы фильтров также являются компонентами Spring, определенными в контексте приложения и, таким образом, могут использовать преимущества богатых возможностей Spring для внедрения зависимостей и интерфейсов жизненного цикла. Spring DelegatingFilterProxyобеспечивает связь между web.xmlконтекстом приложения.

При использовании DelegatingFilterProxy вы увидите в web.xmlфайле что-то вроде этого :

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

<filter-mapping>
   <filter-name>myFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

Обратите внимание, что на самом деле фильтр - это DelegatingFilterProxyкласс, а не класс, который фактически реализует логику фильтра. Что DelegatingFilterProxyделает, так это делегировать методы фильтра бину, который получается из контекста приложения Spring. Это позволяет компоненту использовать преимущества поддержки жизненного цикла контекста веб-приложения Spring и гибкости конфигурации. Компонент должен быть реализован, javax.servlet.Filterи у него должно быть то же имя, что и в элементе filter-name. Прочтите Javadoc для DelegatingFilterProxy для получения дополнительной информации.

Итак, если я вытащу это из своего web.xml, что будет? Мои сервлеты не смогут взаимодействовать с контейнером Spring? **

Ответы:


127

Здесь есть какое-то волшебство, но в конечном итоге все является детерминированной программой.

DelegatingFilterProxy является фильтр , как это было описано выше, целью которого является « делегируя в Спринг-управляемого компонента , который реализует интерфейс фильтра », то есть, он находит боб ( «целевой боб» или «делегат») в приложении Spring context и вызывает его. Как это возможно? Поскольку этот компонент реализует javax.servlet.Filter, вызывается его метод doFilter.

Какой боб называется? DelegatingFilterProxy «поддерживает targetBeanName [...], определяя имя целевого bean-компонента в контексте приложения Spring».

Как вы видели в своем web.xml, имя bean-компонента - « springSecurityFilterChain » .

Итак, в контексте веб-приложения фильтр создает экземпляр bean-компонента с именем «springSecurityFilterChain» в контексте вашего приложения, а затем делегирует ему полномочия с помощью метода doFilter ().

Помните, что контекст вашего приложения определяется ВСЕМИ файлами APPLICATION-CONTEXT (XML). Например: applicationContext.xml И applicationContext-security.xml.

Итак, попробуйте найти в последнем бин с именем "springSecurityFilterChain" ...

... и, вероятно, вы не можете (например, если вы следовали руководству или если вы настроили безопасность с помощью Roo)

В этом волшебство: появился новый элемент для настройки безопасности , что-то вроде

<http auto-config="true" use-expressions="true"> 

поскольку это разрешено http://www.springframework.org/schema/security/spring-security-3.0.xsd , добьется цели.

Когда Spring загружает контекст приложения с помощью файлов XML, если он находит элемент, он пытается настроить безопасность HTTP, то есть стек фильтров и защищенные URL-адреса, а также зарегистрировать FilterChainProxy с именем «springSecurityFilterChain».

В качестве альтернативы вы можете определить bean-компонент классическим способом, а именно:

<beans:bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">

Но это менее рекомендуется, так как вам нужно много настраивать (все фильтры, которые вы собираетесь использовать. А их более десятка).


«applicationContext-security.xml И applicationContext-security.xml» - это одно и то же имя файла дважды.
musiKk

Спасибо musiKk (я думаю, вы можете отредактировать пост напрямую)
jbbarquero

Это было объяснением того, что я все время искал, и все прояснило для меня.
user871611

@jbbarquero: Вы правы, но я не знал, какая версия должна быть правильной. Я склонен оставлять это на усмотрение автора, чтобы случайно не изменить смысл.
musiKk

ХОРОШО. В любом случае, я очень ценю вашу помощь в улучшении моего ответа. Еще раз спасибо, musiKk
jbbarquero

74

Вы знаете, что такое сервлет-фильтр и как он работает? Это очень полезная часть спецификации сервлетов, позволяющая нам применять концепции, подобные АОП, для обслуживания HTTP-запросов. Многие фреймворки используют реализации фильтров для различных целей, и нередко можно найти их собственные реализации, потому что они очень просты в написании и полезны. В приложении Spring большая часть того, что может делать ваше приложение, находится в ваших bean-компонентах Spring. Однако экземпляр фильтра управляется контейнером сервлета. Контейнер создает, инициализирует и уничтожает его. Тем не менее, спецификация сервлета не требует какой-либо интеграции со Spring, поэтому у вас остается действительно полезная концепция (фильтры) без удобного способа привязать ее к вашему приложению Spring и bean-компонентам, которые выполняют эту работу.

Введите DelegatingFilterProxy. Вы пишете реализацию фильтра и делаете ее bean-компонентом Spring, но вместо добавления вашего собственного класса Filter в web.xml вы используете DelegatingFilterProxy и даете ему имя bean-компонента вашего фильтра в контексте Spring. (Если вы явно не указываете имя, оно использует «имя-фильтра».) Затем во время выполнения DelegatingFilterProxy обрабатывает сложность поиска реальной реализации - той, которую вы написали и настроили в Spring, - и маршрутизации запросов к ней. , Таким образом, во время выполнения это как если бы вы указали свой фильтр в файле web.xml, но вы получаете возможность подключить его, как любой другой компонент Spring.

Если вы удалите это сопоставление фильтра из своего web.xml, все будет продолжать работать, но ни один из ваших URL-адресов не будет защищен. (Предполагается, что имя «springSecurityFilterChain» точно описывает то, что он делает.) Это потому, что это отображение фильтрует каждый входящий запрос и передает его фильтру безопасности, который определен в вашем контексте Spring.


Спасибо за публикацию этого яркого комментария. Сейчас я изучаю Spring Security, пытаясь понять его достаточно, чтобы делать настройки. Я понятия не имел, что такое фильтры сервлетов или пружинные фильтры. Ваш бит об АОП проясняет, ПОЧЕМУ можно было бы использовать фильтры вместо использования сервлетов ........ так что вам не нужно снова и снова писать одну и ту же предварительную / постобработку в каждом сервлете / ресурсе
Стив

Вот это да. Это объяснение как раз то, что мне нужно. Спасибо, что поделились своими знаниями.
Чарльз Морин

@Ryan Stewart, если у меня есть два bean-компонента, реализующих интерфейс фильтра в applicationContext, и я хочу выполнить его по порядку, то как я могу это сделать?
Abhishek Nayak

@skaffman, если у меня есть два bean-компонента, реализующих интерфейс фильтра в applicationContext, и я хочу выполнить его по порядку, как я могу это сделать?
Abhishek Nayak

44

Что такое фильтры сервлетов?

Фильтры сервлетов , в общем, являются концепцией Java WebApp. У вас могут быть фильтры сервлетов в любом веб-приложении, независимо от того, используете ли вы платформу Spring в своем приложении.

Эти фильтры могут перехватывать запросы до того, как они достигнут целевого сервлета. Вы можете реализовать общие функции, такие как авторизация, в фильтрах сервлетов. После реализации вы можете настроить фильтр в своем файле web.xml для применения к определенному сервлету, конкретным шаблонам URL-адресов запроса или всем шаблонам URL-адресов.

Где используются фильтры сервлетов?

В современных веб-приложениях таких фильтров может быть несколько десятков. Такие вещи, как авторизация, кеширование, управление сеансом ORM и внедрение зависимостей, часто реализуются с помощью фильтра сервлетов. Все эти фильтры необходимо зарегистрировать в web.xml.

Создание экземпляров фильтров сервлетов - без Spring Framework

Контейнер сервлетов создает экземпляры фильтров, объявленных в, web.xmlи вызывает их в соответствующее время (например, при обслуживании запросов сервлетов). Теперь, если вы похожи на большинство поклонников внедрения зависимостей (DI), вы, вероятно, скажете, что создание экземпляров - это то, что моя структура DI (Spring) делает лучше. Разве я не могу создать свои фильтры сервлетов с помощью Spring, чтобы они подчинялись всем добротам DI?

DelegatingFilterProxy, так что Spring создает ваши экземпляры фильтра

Это где DelegatingFilterProxyшаги. DelegatingFilterProxyЯвляется impelmentation из javax.servlet.Filterинтерфейса , предоставляемого Spring Framework. После настройки DelegatingFilterProxyв web.xml вы можете объявить фактические bean-компоненты, которые выполняют фильтрацию, в конфигурации Spring. Таким образом, Spring создает экземпляры bean-компонентов, которые выполняют фактическую фильтрацию, и вы можете использовать DI для настройки этих bean-компонентов.

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


очень хорошо объяснено.
user4906240

15

Дело в том, что фильтры сервлетов управляются контейнером сервлетов, а не Spring. И вам может потребоваться добавить в фильтры некоторые пружинные компоненты.

Итак, если вам нужно что-то вроде:

public class FooFilter {

    @Inject
    private FooService service;

    public void doFilter(....) { .. }

}

тогда вам понадобится делегирующий прокси-фильтр.


1

Вы правы насчет «клея». Как написано в JavaDocs FilterChainProxy :

FilterChainProxy связан с цепочкой фильтров контейнера сервлета путем добавления стандартного объявления Spring DelegatingFilterProxy в файл приложения web.xml.

Пожалуйста, см. Раздел FIlterChainProxy в блоге За пространством имен Spring Security для отличного объяснения.


0

Я был озадачен «springSecurityFilterChain» в web.xml и нашел этот ответ в документе по безопасности springframework:

Этот <http>элемент инкапсулирует конфигурацию безопасности для веб-уровня вашего приложения. > Он создает bean-компонент FilterChainProxy с именем "springSecurityFilterChain", который поддерживает стек> фильтров безопасности, составляющих конфигурацию веб-безопасности [19]. Некоторые базовые фильтры создаются всегда, а другие будут добавлены в стек в зависимости от> присутствующих дочерних элементов атрибутов. Позиции стандартных фильтров фиксированы (см. Таблицу порядка фильтров во введении> пространства имен), что устраняет общий источник ошибок с предыдущими версиями платформы>, когда пользователям приходилось настраивать цепочку фильтров явно в bean-компонентеFilterChainProxy. Вы, конечно, можете сделать это, если вам нужен полный контроль над конфигурацией.

Вот ссылка http://docs.spring.io/spring-security/site/docs/3.0.x/reference/appendix-namespace.html


0

Прошло много времени, но у меня был тот же вопрос, и я нашел это: https://www.javacodegeeks.com/2013/11/spring-security-behind-the-scenes.html

Я попытался запустить свой весенний проект безопасности, удалив соответствующий фильтр, а также добавив его. Я обнаружил, что если мы добавим фильтр, только тогда вызов будет перенаправлен на требуемую страницу входа, как определено в конфигурации spring -security.

Следовательно, соглашаясь с ответом @Ryan.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.