Jaki jest sens delegowaniaFilterProxy Spring MVC?

120

Widzę to w mojej aplikacji Spring MVC web.xml:

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

Próbuję dowiedzieć się, dlaczego tam jest i czy jest rzeczywiście potrzebny.

Znalazłem to wyjaśnienie w dokumentacji Spring, ale nie pomaga mi to zrozumieć:

Wydaje się, że komponent ten jest „spoiwem” między serwletami zdefiniowanymi w programie web.xmla komponentami zdefiniowanymi w programie Spring applicationContext.xml.

7.1 DelegatingFilterProxy

Korzystając z filtrów serwletów, musisz oczywiście zadeklarować je w swoim web.xml, w przeciwnym razie zostaną zignorowane przez kontener serwletów. W Spring Security klasy filtrów są również ziarnami Springa zdefiniowanymi w kontekście aplikacji, dzięki czemu mogą korzystać z bogatych narzędzi do wstrzykiwania zależności i interfejsów cyklu życia Springa. Spring DelegatingFilterProxyzapewnia łącze między web.xmlkontekstem aplikacji.

Podczas korzystania z DelegatingFilterProxy w web.xmlpliku zobaczysz coś takiego :

<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>

Zauważ, że filtr jest w rzeczywistości a DelegatingFilterProxy, a nie klasą, która faktycznie implementuje logikę filtru. To, co DelegatingFilterProxyrobi, to delegowanie metod filtru do komponentu bean, który jest uzyskiwany z kontekstu aplikacji Spring. Dzięki temu bean może korzystać z obsługi cyklu życia aplikacji internetowej Spring i elastyczności konfiguracji. Fasola musi być implementowana javax.servlet.Filteri musi mieć taką samą nazwę, jak nazwa elementu filter-name. Przeczytaj Javadoc dla DelegatingFilterProxy, aby uzyskać więcej informacji

Więc jeśli to wyciągnę z siebie web.xml, co się stanie? Moje serwlety nie będą w stanie komunikować się z kontenerem Spring? **

Tomasz
źródło

Odpowiedzi:

127

Jest tu jakaś magia, ale na końcu wszystko jest deterministycznym programem.

DelegatingFilterProxy jest filtr jak to zostało wyjaśnione powyżej, którego celem jest " delegowanie do wiosennej zarządzane fasoli, która implementuje interfejs Filter ”, czyli znajdzie Bean ( „target fasoli” lub „Delegat”) w aplikacji Wiosny kontekst i wywołuje go. Jak to jest możliwe? Ponieważ ten komponent bean implementuje javax.servlet.Filter, wywoływana jest jego metoda doFilter.

Która fasola się nazywa? DelegatingFilterProxy "Obsługuje" targetBeanName "[...], określając nazwę docelowego komponentu bean w kontekście aplikacji Spring."

Jak widać w pliku web.xml, nazwa ziarna to „ springSecurityFilterChain .

Tak więc w kontekście aplikacji internetowej filtr tworzy wystąpienie komponentu bean o nazwie „springSecurityFilterChain” w kontekście aplikacji, a następnie przekazuje go do niego za pomocą metody doFilter ().

Pamiętaj, że kontekst twojej aplikacji jest zdefiniowany za pomocą WSZYSTKICH plików KONTEKSTU APLIKACJI (XML). Na przykład: applicationContext.xml AND applicationContext-security.xml.

Spróbuj więc znaleźć fasolę o nazwie „springSecurityFilterChain” w tym ostatnim ...

... i prawdopodobnie nie możesz (na przykład, jeśli skorzystałeś z samouczka lub skonfigurowałeś zabezpieczenia za pomocą Roo)

Oto magia: jest nowy element do konfiguracji zabezpieczeń , coś w rodzaju

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

na co zezwala http://www.springframework.org/schema/security/spring-security-3.0.xsd , załatwi .

Kiedy Spring ładuje kontekst aplikacji przy użyciu plików XML, jeśli znajdzie element, spróbuje ustawić zabezpieczenia HTTP, to znaczy stos filtrów i chronione adresy URL, oraz zarejestrować FilterChainProxy o nazwie „springSecurityFilterChain”.

Alternatywnie możesz zdefiniować fasolę w klasyczny sposób, czyli:

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

Ale jest to mniej zalecane, ponieważ musisz zrobić dużo konfiguracji (wszystkie filtry, których będziesz używać. A jest ich ponad tuzin)

jbbarquero
źródło
„applicationContext-security.xml AND applicationContext-security.xml” to dwukrotnie ta sama nazwa pliku.
musiKk
Dzięki musiKk (myślę, że możesz edytować post bezpośrednio)
jbbarquero
To było wyjaśnienie, którego szukałem przez cały czas i wyjaśniło mi wszystko.
user871611
@jbbarquero: Masz rację, ale nie byłem pewien, jaka powinna być prawidłowa wersja. Zwykle zostawiam to pierwotnemu autorowi, aby naprawił to, aby nieumyślnie nie zmienić znaczenia.
musiKk
DOBRZE. W każdym razie bardzo dziękuję za pomoc w poprawieniu mojej odpowiedzi. Jeszcze raz dziękuję, musiKk
jbbarquero
73

Czy wiesz, co to jest filtr serwletów i jak działa? Jest to bardzo przydatna część specyfikacji serwletu, która pozwala nam zastosować koncepcje podobne do AOP do obsługi żądań HTTP. Wiele frameworków używa implementacji filtrów do różnych rzeczy i nierzadko zdarza się znaleźć ich niestandardowe implementacje, ponieważ są one bardzo proste do napisania i przydatne. W aplikacji Spring większość funkcji, które może wykonać aplikacja, znajduje się w ziarnach Springa. Jednak instancja filtru jest kontrolowana przez kontener Servlet. Kontener tworzy instancję, inicjuje i niszczy go. Specyfikacja serwletu nie wymaga jednak żadnej integracji Springa, więc pozostaje Ci naprawdę przydatna koncepcja (Filtry) bez wygodnego sposobu na powiązanie jej z aplikacją Spring i fasolami, które wykonują pracę.

Wprowadź DelegatingFilterProxy. Piszesz implementację Filter i zmieniasz ją w komponent bean Spring, ale zamiast dodawać własną klasę Filter do pliku web.xml, używasz metody DelegatingFilterProxy i nadajesz jej nazwę bean filtra w kontekście Spring. (Jeśli nie podasz jawnie nazwy, użyje ona „nazwy filtru”). Następnie w czasie wykonywania element DelegatingFilterProxy obsługuje złożoność znajdowania rzeczywistej implementacji - tej, którą napisałeś i skonfigurowałeś w Spring - i kierowania do niej żądań . Tak więc w czasie wykonywania wygląda to tak, jakbyś umieścił swój filtr w pliku web.xml, ale zyskujesz możliwość połączenia go tak, jak każdą inną ziarno Springa.

Jeśli usuniesz mapowanie tego filtra z pliku web.xml, wszystko będzie nadal działać, ale żaden z Twoich adresów URL nie będzie zabezpieczony. (Zakładając, że nazwa „springSecurityFilterChain” dokładnie opisuje, co robi.) To dlatego, że to mapowanie filtruje każde przychodzące żądanie i przekazuje je do filtra bezpieczeństwa zdefiniowanego w kontekście Springa.

Ryan Stewart
źródło
Dziękujemy za opublikowanie tego pouczającego komentarza. Uczę się teraz Spring Security, próbując zrozumieć go na tyle, aby dokonać dostosowań. Nie miałem pojęcia, jakie są filtry serwletów ani jakie są filtry sprężynowe. Twój fragment o AOP wyjaśnia, DLACZEGO można mieć filtry zamiast po prostu używać serwletów ........ więc nie musisz w kółko pisać tego samego przetwarzania wstępnego / końcowego w każdym serwlecie / zasobie
Steve
Łał. To wyjaśnienie jest dokładnie tym, czego potrzebowałem. Dziękuję za podzielenie się wiedzą.
Charles Morin,
@Ryan Stewart Jeśli mam dwie fasole implementuje interfejs filtru w applicationContext i chcę wykonać w kolejności, to jak mogę to zrobić?
Abhishek Nayak
@skaffman Jeśli mam dwie fasole implementuje interfejs filtru w applicationContext i chcę wykonać w kolejności, to jak mogę to zrobić?
Abhishek Nayak
44

Co to są filtry serwletów?

Filtry serwletów to ogólnie koncepcja Java WebApp. Możesz mieć filtry serwletów w dowolnej aplikacji internetowej, niezależnie od tego, czy używasz w niej frameworka Spring, czy nie.

Filtry te mogą przechwytywać żądania, zanim dotrą do docelowego serwletu. W filtrach serwletów można zaimplementować typową funkcjonalność, taką jak autoryzacja. Po wdrożeniu możesz skonfigurować filtr w swoim pliku web.xml, aby był stosowany do określonego serwletu, określonych wzorców adresów URL żądań lub wszystkich wzorców adresów URL.

Gdzie są używane filtry serwletów?

Nowoczesne aplikacje internetowe mogą mieć dziesiątki takich filtrów. Takie rzeczy, jak autoryzacja, buforowanie, zarządzanie sesjami ORM i wstrzykiwanie zależności są często implementowane za pomocą filtra serwletów. Wszystkie te filtry należy zarejestrować w web.xml.

Tworzenie instancji filtrów serwletów - bez Spring Framework

Twój kontener serwletów tworzy instancje filtrów zadeklarowanych w programie web.xmli wywołuje je w odpowiednim czasie (tj. Podczas obsługi żądań serwletów). Teraz, jeśli jesteś jak większość fanów Dependency Injection (DI), prawdopodobnie powiedziałbyś, że tworzenie instancji jest tym, co mój framework DI (Spring) robi lepiej. Czy nie mogę uzyskać moich filtrów serwletów utworzonych za pomocą Springa, aby były dostępne dla wszystkich dobroci DI?

DelegatingFilterProxy, więc Spring utworzy Twoje instancje filtrów

Tutaj DelegatingFilterProxywkracza. DelegatingFilterProxyJest impelmentacją javax.servlet.Filterinterfejsu dostarczonego przez Spring Framework. Po skonfigurowaniu DelegatingFilterProxyw web.xml możesz zadeklarować rzeczywiste ziarna, które wykonują filtrowanie w Twojej konfiguracji wiosennej. W ten sposób Spring tworzy instancje ziaren, które faktycznie filtrują, i możesz użyć DI do ich skonfigurowania.

Zauważ, że potrzebujesz tylko jednej DelegatingFilterProxydeklaracji w programie, web.xmlale możesz mieć kilka beanpołączonych ze sobą filtrów w kontekście aplikacji.

Tahir Akhtar
źródło
bardzo dobrze wyjaśnione.
user4906240
15

Rzecz w tym, że filtrami serwletów zarządza kontener serwletów, a nie wiosną. Może być konieczne wstrzyknięcie niektórych elementów sprężyny do filtrów.

Jeśli więc potrzebujesz czegoś takiego:

public class FooFilter {

    @Inject
    private FooService service;

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

}

wtedy potrzebujesz proxy filtru delegującego.

Bozho
źródło
1

Masz rację co do rzeczy „kleju”. Jak napisano w JavaDocs z FilterChainProxy :

Element FilterChainProxy jest połączony z łańcuchem filtrów kontenerów serwletów przez dodanie standardowej deklaracji Spring DelegatingFilterProxy w pliku web.xml aplikacji.

Zapoznaj się z sekcją FIlterChainProxy na blogu Behind the Spring Security Namespace, aby uzyskać doskonałe wyjaśnienie.

Ritesh
źródło
0

Byłem zdumiony przez „springSecurityFilterChain” w web.xml i znalazłem tę odpowiedź w dokumencie bezpieczeństwa springframework:

<http>Elementem obudowuje konfiguracji zabezpieczeń dla warstwy internetowej aplikacji. > Tworzy bean FilterChainProxy o nazwie „springSecurityFilterChain”, który utrzymuje stos> filtrów bezpieczeństwa, które tworzą konfigurację zabezpieczeń sieci [19]. Niektóre filtry podstawowe są zawsze> tworzone, a inne zostaną dodane do stosu w zależności od atrybutów elementów potomnych, które są> obecne. Pozycje filtrów standardowych są stałe (zobacz tabelę kolejności filtrów we> wprowadzeniu do przestrzeni nazw), usuwając typowe źródło błędów z poprzednimi wersjami frameworka>, gdy użytkownicy musieli jawnie skonfigurować łańcuch filtrów w komponencie beanFilterChainProxy. Oczywiście możesz to zrobić,> jeśli potrzebujesz pełnej kontroli nad konfiguracją.

Oto link http://docs.spring.io/spring-security/site/docs/3.0.x/reference/appendix-namespace.html

Janet
źródło
0

Minęło dużo czasu, ale miałem to samo pytanie i znalazłem to: https://www.javacodegeeks.com/2013/11/spring-security-behind-the-scenes.html

Próbowałem uruchomić mój projekt zabezpieczeń wiosennych, usuwając ten filtr, a także dodając go. Odkryłem, że jeśli dodamy filtr, tylko wtedy połączenie przekieruje do wymaganej strony logowania, określonej w konfiguracji zabezpieczeń sprężynowych.

Dlatego zgadzając się na odpowiedź @ Ryan.

Z umysłu
źródło