Qual è il punto di DelegatingFilterProxy di Spring MVC?


120

Vedo questo nella mia app Spring MVC web.xml:

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

Sto cercando di capire perché è lì e se è effettivamente necessario.

Ho trovato questa spiegazione nei documenti di primavera ma non mi aiuta a capirla:

Sembra suggerire che questo componente sia il "collante" tra i servlet definiti in web.xmle i componenti definiti in Spring applicationContext.xml.

7.1 DelegatingFilterProxy

Quando si utilizzano filtri servlet, è ovviamente necessario dichiararli nel proprio web.xml, altrimenti verranno ignorati dal contenitore servlet. In Spring Security, le classi di filtro sono anche bean Spring definiti nel contesto dell'applicazione e quindi in grado di sfruttare le ricche funzionalità di inserimento delle dipendenze e le interfacce del ciclo di vita di Spring. Spring's DelegatingFilterProxyfornisce il collegamento tra web.xmle il contesto dell'applicazione.

Quando usi DelegatingFilterProxy, vedrai qualcosa di simile nel web.xmlfile:

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

Si noti che il filtro è effettivamente a DelegatingFilterProxye non la classe che implementerà effettivamente la logica del filtro. Ciò che DelegatingFilterProxyfa è delegare i metodi del filtro a un bean ottenuto dal contesto dell'applicazione Spring. Ciò consente al bean di beneficiare del supporto del ciclo di vita del contesto dell'applicazione Web Spring e della flessibilità di configurazione. Il bean deve essere implementato javax.servlet.Filtere deve avere lo stesso nome di quello nell'elemento nome-filtro. Leggere Javadoc per DelegatingFilterProxy per ulteriori informazioni

Quindi, se lo tolgo dal mio web.xml, cosa succederà? I miei servlet non saranno in grado di comunicare con il contenitore Spring? **

Risposte:


127

C'è una sorta di magia qui, ma alla fine, tutto è un programma deterministico.

Il DelegatingFilterProxy è un filtro come è stato spiegato in precedenza, il cui obiettivo è " la delega ad un bean Spring gestiti che implementa l'interfaccia Filter ", che è, esso trova un fagiolo ( "target fagiolo" o "delegato") nell'applicazione primavera contesto e lo invoca. Come è possibile? Poiché questo bean implementa javax.servlet.Filter, viene chiamato il suo metodo doFilter.

Quale fagiolo si chiama? il DelegatingFilterProxy "Supporta un" targetBeanName "[...], specificando il nome del bean di destinazione nel contesto dell'applicazione Spring."

Come hai visto nel tuo web.xml, il nome del bean è " springSecurityFilterChain " .

Quindi, nel contesto di un'applicazione web, un Filter crea un'istanza di un bean chiamato "springSecurityFilterChain" nel contesto dell'applicazione e quindi delegato ad esso tramite il metodo doFilter ().

Ricorda, il contesto dell'applicazione è definito con TUTTI i file APPLICATION-CONTEXT (XML). Ad esempio: applicationContext.xml AND applicationContext-security.xml.

Quindi prova a trovare un fagiolo chiamato "springSecurityFilterChain" in quest'ultimo ...

... e probabilmente non puoi (ad esempio se hai seguito un tutorial o se hai configurato la sicurezza utilizzando Roo)

Ecco la magia: c'è un nuovo elemento per configurare la sicurezza , qualcosa di simile

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

come consentito da http://www.springframework.org/schema/security/spring-security-3.0.xsd , farà il trucco.

Quando Spring carica il contesto dell'applicazione utilizzando file XML, se trova un elemento, proverà a impostare la sicurezza HTTP, ovvero uno stack di filtri e URL protetti, ea registrare il FilterChainProxy denominato "springSecurityFilterChain".

In alternativa, puoi definire il fagiolo nel modo classico, ovvero:

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

Ma è meno consigliato, dal momento che è necessario eseguire molte configurazioni (tutti i filtri che utilizzerai. E ce ne sono più di una dozzina)


"applicationContext-security.xml AND applicationContext-security.xml" ha lo stesso nome di file due volte.
musiKk

Grazie musiKk (penso che tu possa modificare il post direttamente)
jbbarquero

Questa era la spiegazione che stavo cercando e mi ha chiarito le cose.
user871611

@jbbarquero: hai ragione ma non ero sicuro di quale dovrebbe essere la versione corretta. Tendo a lasciare che sia l'autore originale a correggerlo in modo da non modificare inavvertitamente il significato.
musiKk

OK. In ogni caso, apprezzo molto il tuo aiuto per migliorare la mia risposta. Grazie ancora, musiKk
jbbarquero

73

Sai cos'è un filtro servlet e come funziona? È una parte molto utile della specifica Servlet, che ci consente di applicare concetti simili a AOP alla gestione delle richieste HTTP. Molti framework utilizzano implementazioni di filtri per varie cose e non è raro trovarne implementazioni personalizzate perché sono molto semplici da scrivere e utili. In un'app Spring, la maggior parte delle cose che la tua app può fare è nei tuoi bean Spring. Un'istanza Filter, tuttavia, è controllata dal contenitore Servlet. Il contenitore lo istanzia, lo inizializza e lo distrugge. La Servlet Spec non richiede alcun tipo di integrazione Spring, quindi ti rimane un concetto davvero utile (filtri) senza alcun modo conveniente per collegarlo alla tua app Spring e ai bean che fanno il lavoro.

Immettere il DelegatingFilterProxy. Si scrive un'implementazione del filtro e lo si rende un bean Spring, ma invece di aggiungere la propria classe Filter a web.xml, si utilizza DelegatingFilterProxy e gli si assegna il nome del bean del filtro nel contesto Spring. (Se non fornisci esplicitamente un nome, utilizza il "nome-filtro".) Quindi in fase di esecuzione, DelegatingFilterProxy gestisce la complessità di trovare l'implementazione reale - quella che hai scritto e configurato in Spring - e di instradare le richieste ad essa . Quindi in fase di esecuzione, è come se avessi elencato il tuo filtro in web.xml, ma hai il vantaggio di poterlo cablare come qualsiasi altro bean Spring.

Se rimuovi la mappatura del filtro dal tuo web.xml, tutto continuerà a funzionare, ma nessuno dei tuoi URL sarà protetto. (Questo presuppone che il nome "springSecurityFilterChain" descriva accuratamente ciò che fa.) Questo perché questa mappatura filtra ogni richiesta in arrivo e la trasmette a un filtro di sicurezza definito nel tuo contesto Spring.


Grazie per aver postato questo commento illuminante. Sto imparando Spring Security ora, cercando di capirlo abbastanza per fare personalizzazioni. Non avevo idea di cosa fossero i filtri servlet o cosa fossero i filtri a molla. La tua parte su AOP rende chiaro PERCHÉ si dovrebbero avere filtri invece di usare solo servlet ........ quindi non devi scrivere la stessa pre / post elaborazione più e più volte in ogni servlet / risorsa
Steve

Wow. Quella spiegazione è esattamente ciò di cui avevo bisogno. Grazie per aver condiviso la tua conoscenza.
Charles Morin

@ Ryan Stewart se ho due bean implementa l'interfaccia Filter in applicationContext e voglio eseguire in un ordine, allora come posso farlo?
Abhishek Nayak

@skaffman se ho due bean implementa l'interfaccia Filter in applicationContext e voglio eseguire in un ordine, allora come posso farlo?
Abhishek Nayak

44

Cosa sono i filtri servlet?

I filtri servlet sono, in generale, un concetto di Java WebApp. Puoi avere filtri servlet in qualsiasi webapp, indipendentemente dal fatto che utilizzi o meno il framework Spring nella tua applicazione.

Questi filtri possono intercettare le richieste prima che raggiungano il servlet di destinazione. È possibile implementare funzionalità comuni, come l'autorizzazione, nei filtri servlet. Una volta implementato, puoi configurare il filtro nel tuo web.xml da applicare a un servlet specifico, a specifici modelli di URL di richiesta oa tutti i modelli di URL.

Dove vengono utilizzati i filtri servlet?

Le moderne web-app possono avere dozzine di tali filtri. Cose come l'autorizzazione, la memorizzazione nella cache, la gestione della sessione ORM e l'inserimento delle dipendenze sono spesso implementate con l'aiuto del filtro servlet. Tutti questi filtri devono essere registrati in web.xml.

Creazione di istanze di filtri servlet - senza Spring Framework

Il tuo contenitore servlet crea istanze di filtri dichiarati in web.xmle li chiama al momento opportuno (cioè, quando servono le richieste servlet). Ora, se sei come la maggior parte dei fan di Dependency Injection (DI), probabilmente diresti che la creazione di istanze è ciò che il mio framework DI (Spring) fa meglio. Non posso creare i miei filtri servlet con Spring in modo che siano suscettibili di tutte le bontà DI?

DelegatingFilterProxy, in modo che Spring crei le istanze del filtro

Qui è dove DelegatingFilterProxyentra in gioco DelegatingFilterProxyun'implementazione javax.servlet.Filterdell'interfaccia fornita da Spring Framework. Una volta configurato DelegatingFilterProxyin web.xml, puoi dichiarare i bean effettivi che eseguono il filtraggio nella configurazione primaverile. In questo modo, Spring crea le istanze di bean che eseguono il filtraggio effettivo e puoi utilizzare DI per configurare questi bean.

Notare che è necessaria solo una singola DelegatingFilterProxydichiarazione in web.xmlma è possibile avere diversi filtri beanconcatenati nel contesto dell'applicazione.


molto ben spiegato.
user4906240

15

Il fatto è che i filtri servlet sono gestiti dal contenitore servlet e non dalla primavera. E potrebbe essere necessario iniettare alcuni componenti a molla nei filtri.

Quindi, se hai bisogno di qualcosa come:

public class FooFilter {

    @Inject
    private FooService service;

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

}

allora hai bisogno del proxy del filtro di delega.


1

Hai ragione riguardo alle cose "colla". Come scritto in JavaDocs di FilterChainProxy :

FilterChainProxy è collegato alla catena di filtri del contenitore servlet aggiungendo una dichiarazione Spring DelegatingFilterProxy standard nel file web.xml dell'applicazione.

Si prega di consultare la sezione FIlterChainProxy del blog Behind the Spring Security Namespace per un'eccellente spiegazione.


0

Sono rimasto perplesso da "springSecurityFilterChain" in web.xml e ho trovato questa risposta nel documento sulla sicurezza di springframework:

L' <http>elemento incapsula la configurazione di sicurezza per il livello web della tua applicazione. > Crea un bean FilterChainProxy denominato "springSecurityFilterChain" che mantiene lo stack di> filtri di sicurezza che compongono la configurazione della sicurezza web [19]. Alcuni filtri di base sono sempre> creati e altri verranno aggiunti allo stack a seconda degli attributi> elementi figlio che sono presenti. Le posizioni dei filtri standard sono fisse (vedere la tabella dell'ordine dei filtri nella> introduzione allo spazio dei nomi), rimuovendo una fonte comune di errori con le versioni precedenti del framework> quando gli utenti dovevano configurare esplicitamente la catena dei filtri nel bean FilterChainProxy. Ovviamente puoi ancora farlo se hai bisogno del pieno controllo della configurazione.

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


0

È passato molto tempo ma ho avuto la stessa domanda e ho trovato questo: https://www.javacodegeeks.com/2013/11/spring-security-behind-the-scenes.html

Ho provato a eseguire il mio progetto di sicurezza primaverile rimuovendo il filtro in questione e aggiungendolo. Quello che ho trovato è che se aggiungiamo il filtro, solo allora la chiamata verrà reindirizzata alla pagina di accesso richiesta come definita nella configurazione Spring-Security.

Quindi, accettando la risposta di @ Ryan.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.