Який сенс Spring MVC's DelegatingFilterProxy?


120

Я бачу це у своєму весняному додатку MVC web.xml:

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

Я намагаюся розібратися, чому це там і чи потрібно насправді.

Я знайшов це пояснення у весняних документах, але це не допомагає мені зрозуміти це:

Здається, це дозволяє припустити, що цей компонент є "клеєм" між сервлетами, визначеними в, web.xmlта компонентами, визначеними навесні applicationContext.xml.

7.1 Делегування фільтраПрокси

Використовуючи фільтри сервлетів, вам, очевидно, потрібно оголосити їх у своєму web.xml, інакше контейнер сервлетів буде ігнорований. У Spring Security класами фільтрів також є "Весняні боби", визначені в контексті програми, і тому вони можуть скористатися багатими можливостями введення залежностей Spring і інтерфейсами життєвого циклу. Spring's 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. Це дає можливість квасолі скористатись підтримкою життєвого циклу контексту Веб-програми та гнучкістю конфігурації. Бін повинен реалізовувати, javax.servlet.Filterі він повинен мати те саме ім'я, що і в елементі імені фільтра. Прочитайте Javadoc для DelegatingFilterProxy для отримання додаткової інформації

Отже, якщо я вийму це зі свого web.xml, що буде? Мої сервлети не зможуть спілкуватися з контейнером Spring? **

Відповіді:


127

Тут є якась магія, але наприкінці все - це детермінована програма.

DelegatingFilterProxy є фільтр , як це було описано вище, метою якого є « делегуючи в Спрінг-керованого компонента , який реалізує інтерфейс фільтра », тобто, він знаходить боб ( «цільової боб» або «делегат») в додатку Spring контекст і викликає його. Як це можливо? Оскільки цей боб реалізує javax.servlet.Filter, його метод doFilter називається.

Яку квасолю називають? DelegatingFilterProxy "Підтримує" targetBeanName "[...], вказуючи назву цільового квасолі у контексті програми Spring."

Як ви бачили на своєму web.xml, назва квасолі - " springSecurityFilterChain " .

Таким чином, у контексті веб-програми фільтр створює екземпляр під назвою "springSecurityFilterChain" у вашому контексті програми, а потім делегує його за допомогою методу doFilter ().

Пам’ятайте, що ваш контекст програми визначено ВСІМ ДОПОМОГОМ-КОНТЕКСТ (XML) файлами. Наприклад: applicationContext.xml AND 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".

Можна також визначити квасоля класичним способом, тобто:

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

Але це менш рекомендується, оскільки вам потрібно зробити багато конфігурації (всі фільтри, які ви збираєтеся використовувати. І їх більше десятка)


"applicationContext-security.xml AND applicationContext-security.xml" - це те саме ім'я файлу двічі.
musiKk

Дякую musiKk (я думаю, ви можете редагувати публікацію безпосередньо)
jbbarquero

Це було поясненням того, що я весь час переглядав і розбирав речі.
користувач871611

@jbbarquero: Ти маєш рацію, але я не знав, якою має бути правильна версія. Я схильний залишити це для оригінального автора виправити так, щоб ненароком не змінити значення.
musiKk

ГАРАЗД. У будь-якому випадку, я дуже ціную вашу допомогу, щоб покращити мою відповідь. Ще раз дякую, musiKk
jbbarquero

73

Чи знаєте ви, що таке фільтр сервлетів і як він працює? Це дуже корисний фрагмент Spev Servlet, що дозволяє нам застосовувати AOP-подібні концепції для обслуговування HTTP-запитів. Багато фреймворків використовують реалізацію фільтрів для різних речей, і нечасто знайти власні реалізації їх, оскільки вони дуже прості в написанні та корисні. У весняному додатку більшість речей, які може зробити ваш додаток, є у ваших весняних бобах. Екземпляр фільтру, однак, контролюється контейнером Servlet. Контейнер інстанціює, ініціалізує і знищує його. Спекуляція Servlet не вимагає будь-якої інтеграції весни, тому вам залишається дійсно корисна концепція (Фільтри), не маючи зручного способу прив’язати її до програми Spring та бобів, які роблять цю роботу.

Введіть DelegatingFilterProxy. Ви пишете реалізацію фільтру і перетворюєте його на весняний квасоля, але замість того, щоб додати свій власний клас фільтру до web.xml, ви використовуєте DelegatingFilterProxy і даєте йому ім'я для вашого фільтра у контексті Spring. (Якщо явно не вказати ім'я, воно використовує "ім'я фільтра".) Тоді під час виконання DelegatingFilterProxy вирішує складність пошуку реальної реалізації - тієї, яку ви написали та налаштували навесні - та маршрутизації запитів до неї. . Так що під час виконання, це як би ви перерахували свій фільтр у web.xml, але ви отримаєте користь від того, що зможете провести його як будь-який інший весняний боб.

Якщо ви витяжете це зіставлення фільтрів із веб-файлу web.xml, усе продовжить працювати, але жодна з ваших URL-адрес не буде захищена. (Це припускаючи, що назва "springSecurityFilterChain" точно описує, що вона робить.) Це тому, що це зіставлення фільтрує кожен вхідний запит і передає його фільтру безпеки, визначеному у вашому контексті Spring.


Дякуємо, що опублікували цей освітлюючий коментар. Зараз я навчаюсь Spring Security, намагаюся зрозуміти її досить, щоб зробити налаштування. Я поняття не мав, що таке фільтри сервлетів або що таке пружинні фільтри. Ваш трішки про AOP дає зрозуміти, Чому у вас будуть фільтри замість того, щоб просто використовувати сервлети ........ тож вам не доведеться писати однакову переробку до / після повторної операції у кожному сервлеті / ресурсі
Стів

Ого. Це пояснення - саме те, що мені було потрібно. Дякую, що поділилися своїми знаннями.
Чарльз Морін

@ Райан Стюарт, якщо у мене є два боби, що реалізують інтерфейс фільтру у applicationContext, і я хочу виконати замовлення, то як я можу це зробити?
Абхішек Наяк

@skaffman, якщо у мене є два боби, що реалізує інтерфейс фільтру у applicationContext, і я хочу виконати замовлення, то як я можу це зробити?
Абхішек Наяк

44

Що таке фільтри сервлетів?

Фільтри сервлетів - це взагалі концепція Java WebApp. Ви можете мати фільтри сервлетів у будь-якому веб-сайті, незалежно від того, використовуєте Ви у своїй програмі Spring Framework.

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

Де використовуються фільтри сервлетів?

Сучасні веб-додатки можуть мати десятки таких фільтрів. Такі речі, як авторизація, кешування, керування сеансами ORM та введення залежності часто реалізуються за допомогою фільтра сервлетів. Усі ці фільтри потрібно зареєструвати web.xml.

Моментальні фільтри сервлетів - без Spring Framework

Ваш контейнер сервлетів створює екземпляри оголошених фільтрів web.xmlі викликає їх у відповідний час (тобто під час обслуговування запитів сервлетів). Тепер, якщо ви схожі на більшість шанувальників Dependency Injection (DI), ви, ймовірно, скажете, що створення екземплярів - це те, що моя рамка DI (Spring) робить краще. Чи не можу я створити свої фільтри сервлетів, створені за допомогою Spring, щоб вони піддавалися всім хорошим DI?

DelegatingFilterProxy, так що Spring створює ваші екземпляри фільтра

Ось тут DelegatingFilterProxyкроки в. DelegatingFilterProxy- це спонукання javax.servlet.Filterінтерфейсу, який надає Spring Framework. Після налаштування DelegatingFilterProxyв web.xml ви можете оголосити фактичну фасолю, яка виконує фільтрацію у вашій весняній конфігурації. Таким чином, Spring створює екземпляри бобів, які роблять фактичну фільтрацію, і ви можете використовувати DI для налаштування цих бобів.

Зауважте, що вам потрібна лише одна DelegatingFilterProxyзаява, web.xmlале beanу вашому додатку може бути кілька фільтрованих ланцюгів.


дуже добре пояснено.
user4906240

15

Справа в тому, що фільтри сервлетів управляються контейнером сервлетів, а не весною. І вам може знадобитися ввести деякі пружинні компоненти у ваші фільтри.

Отже, якщо вам потрібно щось на зразок:

public class FooFilter {

    @Inject
    private FooService service;

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

}

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


1

Ви маєте рацію щодо «склеювання» речей. Як написано в JavaDocs з FilterChainProxy :

FilterChainProxy пов'язаний у ланцюг фільтрів контейнерів сервлетів шляхом додавання стандартного декларації Spring DelegatingFilterProxy у файл web.xml програми.

Будь ласка, дивіться розділ FIlterChainProxy в блозі За Spring Spring Іменний простір для відмінного пояснення.


0

Мене здивувало "springSecurityFilterChain" в web.xml і знайшов цю відповідь у документі безпеки Springframework:

<http>Елемент инкапсулирует конфігурацію безпеки для веб - шар додатки. > Він створює фільтр FilterChainProxy під назвою "springSecurityFilterChain", який підтримує стек> фільтрів безпеки, що складають конфігурацію веб-безпеки [19]. Деякі основні фільтри завжди> створюються, а інші додаватимуться до стеку залежно від атрибутів, які є дочірніми елементами. Позиції стандартних фільтрів виправлені (див. Таблицю порядку фільтрів у введенні в область імен), видаляючи загальне джерело помилок з попередніми версіями фреймворку>, коли користувачі повинні були чітко налаштувати ланцюжок фільтрів у квасолі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

Я спробував запустити мій весняний проект безпеки, видаливши відповідний фільтр, а також додавши його. Що я знайшов, якщо ми додамо фільтр, тільки тоді виклик буде перенаправлений на потрібну сторінку входу, як визначено в конфігурації джерела безпеки.

Отже, погоджуючись на відповідь @ Райана.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.