Panoramica e necessità di DelegatingFilterProxy in primavera

1. Panoramica

Il DelegatingFilterProxy è un filtro servlet che permette il passaggio di controllo di filtro classi che hanno accesso al contesto di applicazione Spring. Spring Security fa molto affidamento su questa tecnica.

In questo tutorial, lo tratteremo in dettaglio.

2. DelegatingFilterProxy

Javadoc per DelegatingFilterProxy afferma che si tratta di un file

Proxy per un filtro servlet standard, che delega a un bean gestito da Spring che implementa l'interfaccia del filtro.

Quando si utilizzano filtri servlet, è ovviamente necessario dichiararli come classe filtro nel nostro Java-config o web.xml , altrimenti il ​​contenitore servlet li ignorerà. DelegatingFilterProxy di Spring fornisce il collegamento tra web.xml e il contesto dell'applicazione.

2.1. Funzionamento interno di DelegatingFilterProxy

Diamo un'occhiata a come DelegatingFilterProxy trasferisce il controllo al nostro bean Spring.

Durante l'inizializzazione, DelegatingFilterProxy recupera il nome del filtro e recupera il bean con quel nome da Spring Application Context. Questo bean deve essere di tipo javax.Servlet.Filter, ovvero un filtro servlet "normale". Le richieste in arrivo verranno quindi passate a questo bean di filtro.

In breve, il metodo doFilter () di DelegatingFilterProxy delegherà tutte le chiamate a un bean Spring, consentendoci di utilizzare tutte le funzionalità di Spring all'interno del nostro bean di filtro.

Se stiamo utilizzando una configurazione basata su Java, la nostra registrazione del filtro in ApplicationInitializer sarà definita come:

@Override protected javax.servlet.Filter[] getServletFilters() { DelegatingFilterProxy delegateFilterProxy = new DelegatingFilterProxy(); delegateFilterProxy.setTargetBeanName("applicationFilter");   return new Filter[]{delegateFilterProxy}; }

Se usiamo XML, quindi, nel file web.xml :

 applicationFilter org.springframework.web.filter.DelegatingFilterProxy 

Ciò significa che qualsiasi richiesta può essere fatta per passare attraverso il filtro definito come Spring bean con il nome applicationFilter .

2.2. Necessità di DelegatingFilterProxy

DelegatingFilterProxy è una classe nel modulo Web di Spring. Fornisce funzionalità per far passare le chiamate HTTP attraverso i filtri prima di raggiungere la destinazione effettiva. Con l'aiuto di DelegatingFilterProxy, una classe che implementa l' interfaccia javax.Servlet.Filter può essere collegata alla catena di filtri.

Ad esempio, Spring Security utilizza DelegatingFilterProxy per sfruttare le funzionalità di inserimento delle dipendenze di Spring e le interfacce del ciclo di vita per i filtri di sicurezza.

DelegatingFilterProxy sfrutta anche il richiamo di filtri specifici o multipli secondo i percorsi dell'URI di richiesta fornendo la configurazione nel contesto dell'applicazione di Spring o in web.xml.

3. Creazione di un filtro personalizzato

Come descritto sopra, DelegatingFilterProxy è un filtro servlet stesso che delega a uno specifico bean gestito da Spring che implementa l' interfaccia del filtro .

Nelle prossime sezioni, creeremo un filtro personalizzato e lo configureremo utilizzando una configurazione basata su Java e XML.

3.1. Classe di filtro

Creeremo un semplice filtro che registra le informazioni sulla richiesta prima che la richiesta proceda ulteriormente.

Creiamo prima una classe di filtro personalizzata:

@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 implementa javax.Servlet.Filter . Questa classe ha un'annotazione @Component da registrare come bean Spring nel contesto dell'applicazione. In questo modo, la classe DelegatingFilterProxy può trovare la nostra classe di filtri durante l'inizializzazione della catena di filtri.

Si noti che il nome del bean Spring deve essere uguale al valore nel nome del filtro fornito durante la registrazione del filtro personalizzato nella classe ApplicationInitializer o in web.xml in un secondo momento perché la classe DelegatingFilterProxy cercherà il bean del filtro con l'esatta stesso nome nel contesto dell'applicazione.

Se non riesce a trovare un bean con questo nome, solleverà un'eccezione all'avvio dell'applicazione.

3.2. Configurazione del filtro tramite Java Configuration

Per registrare un filtro personalizzato utilizzando la configurazione Java, è necessario sovrascrivere il metodo getServletFilters () di 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. Configurazione del filtro tramite web.xml

Vediamo come appare la configurazione del filtro in web.xml :

 loggingFilter org.springframework.web.filter.DelegatingFilterProxy   loggingFilter /* 

L' argomento della classe filtro è di tipo DelegatingFilterProxy e non della classe filtro che abbiamo creato. Se eseguiamo questo codice e raggiungiamo un URL, il metodo doFilter () di CustomFilter verrà eseguito e visualizzerà i dettagli delle informazioni sulla richiesta nel file di registro.

4. Conclusione

In questo articolo, abbiamo spiegato come funziona DelegatingFilterProxy e come usarlo.

Spring Security fa un ampio uso di DelegatingFilterProxy per proteggere le chiamate e le risorse API Web da accessi non autorizzati.

Il codice sorgente è disponibile su GitHub.