¿Cuál es el punto de DelegatingFilterProxy de Spring MVC?

120

Veo esto en mi aplicación Spring MVC web.xml:

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

Estoy tratando de averiguar por qué está ahí y si realmente es necesario.

Encontré esta explicación en los documentos de Spring pero no me ayuda a darle sentido:

Parece sugerir que este componente es el "pegamento" entre los servlets definidos en web.xmly los componentes definidos en Spring applicationContext.xml.

7.1 Delegación de filtro proxy

Cuando use filtros de servlets, obviamente debe declararlos en su web.xml, o serán ignorados por el contenedor de servlets. En Spring Security, las clases de filtro también son beans de Spring definidos en el contexto de la aplicación y, por lo tanto, pueden aprovechar las ricas instalaciones de inyección de dependencias y las interfaces de ciclo de vida de Spring. Spring DelegatingFilterProxyproporciona el vínculo entre web.xmly el contexto de la aplicación.

Al usar DelegatingFilterProxy, verá algo como esto en el web.xmlarchivo:

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

Observe que el filtro es en realidad a DelegatingFilterProxy, y no la clase que realmente implementará la lógica del filtro. Lo que DelegatingFilterProxyhace es delegar los métodos del filtro a través de un bean que se obtiene del contexto de la aplicación Spring. Esto permite que el bean se beneficie del soporte del ciclo de vida del contexto de la aplicación web Spring y la flexibilidad de configuración. El bean debe implementarse javax.servlet.Filtery debe tener el mismo nombre que el del elemento filter-name. Lea el Javadoc para DelegatingFilterProxy para obtener más información

Entonces, si saco esto de mi web.xml, ¿qué pasará? ¿Mis servlets no podrán comunicarse con el contenedor Spring? **

Thomas
fuente

Respuestas:

127

Hay algo de magia aquí, pero al final, todo es un programa determinista.

El DelegatingFilterProxy es un filtro como se explicó anteriormente, cuyo objetivo es " delegar a un bean administrado por Spring que implementa la interfaz de filtro ", es decir, encuentra un bean ("bean de destino" o "delegado") en su aplicación Spring contexto y lo invoca. ¿Como es posible? Debido a que este bean implementa javax.servlet.Filter, se llama a su método doFilter.

¿Qué frijol se llama? el DelegatingFilterProxy "Admite un" targetBeanName "[...], especificando el nombre del bean de destino en el contexto de la aplicación Spring".

Como vio en su web.xml, el nombre del bean es " springSecurityFilterChain " .

Entonces, en el contexto de una aplicación web, un Filtro crea una instancia de un bean llamado "springSecurityFilterChain" en el contexto de su aplicación y luego lo delega a través del método doFilter ().

Recuerde, el contexto de su aplicación se define con TODOS LOS archivos DE CONTEXTO DE APLICACIÓN (XML). Por ejemplo: applicationContext.xml Y applicationContext-security.xml.

Intente encontrar un bean llamado "springSecurityFilterChain" en este último ...

... y probablemente no puedas (por ejemplo, si siguió un tutorial o si configuró la seguridad usando Roo)

Aquí está la magia: hay un nuevo elemento para configurar la seguridad , algo como

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

como lo permite http://www.springframework.org/schema/security/spring-security-3.0.xsd , hará el truco.

Cuando Spring carga el contexto de la aplicación usando archivos XML, si encuentra un elemento, intentará configurar la seguridad HTTP, es decir, una pila de filtros y URL protegidas y registrar el FilterChainProxy llamado "springSecurityFilterChain".

Alternativamente, puede definir el bean de la forma clásica, es decir:

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

Pero es menos recomendable, ya que necesitas hacer mucha configuración (todos los filtros que vas a usar. Y hay más de una docena de ellos)

jbbarquero
fuente
"applicationContext-security.xml AND applicationContext-security.xml" es el mismo nombre de archivo dos veces.
musiKk
Gracias musiKk (creo que puedes editar la publicación directamente)
jbbarquero
Esta fue la explicación que estuve buscando todo el tiempo y me aclaró las cosas.
user871611
@jbbarquero: Tienes razón, pero no estaba seguro de cuál debería ser la versión correcta. Tiendo a dejar eso para que el autor original lo arregle para no cambiar inadvertidamente el significado.
musiKk
OKAY. En cualquier caso, agradezco mucho tu ayuda para mejorar mi respuesta. Gracias de nuevo, musiKk
jbbarquero
73

¿Sabes qué es un filtro de servlet? y cómo funciona? Es una pieza muy útil de Servlet Spec, que nos permite aplicar conceptos similares a AOP al servicio de solicitudes HTTP. Muchos marcos usan implementaciones de filtros para varias cosas, y no es raro encontrar implementaciones personalizadas de ellos porque son muy simples de escribir y útiles. En una aplicación de Spring, la mayoría de las cosas que puede hacer su aplicación están en sus beans de Spring. Sin embargo, una instancia de Filtro está controlada por el contenedor Servlet. El contenedor lo instancia, lo inicializa y lo destruye. Sin embargo, Servlet Spec no requiere ningún tipo de integración Spring, por lo que te queda un concepto realmente útil (Filtros) sin una forma conveniente de vincularlo a tu aplicación Spring y los beans que hacen el trabajo.

Introduzca DelegatingFilterProxy. Usted escribe una implementación de Filtro y la convierte en un bean Spring, pero en lugar de agregar su propia clase Filter al web.xml, usa DelegatingFilterProxy y le da el nombre del bean de su filtro en el contexto Spring. (Si no proporciona explícitamente un nombre, utiliza el "nombre-filtro"). Luego, en tiempo de ejecución, DelegatingFilterProxy maneja la complejidad de encontrar la implementación real, la que escribió y configuró en Spring, y enrutar las solicitudes a ella. . Entonces, en tiempo de ejecución, es como si hubiera incluido su filtro en web.xml, pero obtiene el beneficio de poder conectarlo como cualquier otro bean Spring.

Si elimina ese mapeo de filtro de su web.xml, todo seguirá funcionando, pero ninguna de sus URL estará protegida. (Eso es asumiendo que el nombre "springSecurityFilterChain" describe con precisión lo que hace). Eso es porque este mapeo está filtrando cada solicitud entrante y entregándola a un filtro de seguridad que está definido en su contexto Spring.

Ryan Stewart
fuente
Gracias por publicar este esclarecedor comentario. Ahora estoy aprendiendo Spring Security, tratando de entenderlo lo suficiente como para hacer personalizaciones. No tenía idea de qué eran los filtros de servlets o qué son los filtros de resortes. Su parte sobre AOP deja en claro POR QUÉ uno tendría filtros en lugar de simplemente usar servlets ... para que no tenga que escribir el mismo procesamiento previo / posterior una y otra vez en cada servlet / recurso
Steve
Guau. Esa explicación es exactamente lo que necesitaba. Gracias por compartir tu conocimiento.
Charles Morin
@Ryan Stewart si tengo dos beans implementa la interfaz de filtro en applicationContext y quiero ejecutar en un orden, ¿cómo puedo hacerlo?
Abhishek Nayak
@skaffman si tengo dos beans implementa la interfaz de filtro en applicationContext, y quiero ejecutar en un orden, ¿cómo puedo hacerlo?
Abhishek Nayak
44

¿Qué son los filtros de servlet?

Los filtros de servlet son, en general, un concepto de aplicación web Java. Puede tener filtros de servlet en cualquier aplicación web, ya sea que use Spring Framework en su aplicación o no.

Estos filtros pueden interceptar solicitudes antes de que lleguen al servlet de destino. Puede implementar funciones comunes, como la autorización, en filtros de servlets. Una vez implementado, puede configurar el filtro en su web.xml para que se aplique a un servlet específico, patrones de URL de solicitud específicos o todos los patrones de URL.

¿Dónde se utilizan filtros de servlets?

Las aplicaciones web modernas pueden tener docenas de estos filtros. Cosas como la autorización, el almacenamiento en caché, la administración de sesiones de ORM y la inyección de dependencias a menudo se implementan con la ayuda del filtro de servlets. Todos estos filtros deben estar registrados en web.xml.

Creación de instancias de filtros de servlet, sin Spring Framework

Su contenedor de servlets crea instancias de filtros declarados web.xmly los llama en los momentos adecuados (es decir, cuando atiende solicitudes de servlets). Ahora, si usted es como la mayoría de los fanáticos de la inyección de dependencia (DI), probablemente diría que la creación de instancias es lo que hace mejor mi marco DI (Spring). ¿No puedo crear mis filtros de servlets con Spring para que sean compatibles con todas las bondades de DI?

DelegatingFilterProxy, para que Spring cree sus instancias de filtro

Aquí es donde DelegatingFilterProxyintervienen los pasos. DelegatingFilterProxyEs un impulso de la javax.servlet.Filterinterfaz proporcionada por Spring Framework. Una vez que configure DelegatingFilterProxyen web.xml, puede declarar los beans reales que hacen el filtrado en su configuración de primavera. De esta forma, Spring crea las instancias de beans que realizan el filtrado real, y puede usar DI para configurar estos beans.

Tenga en cuenta que solo necesita una DelegatingFilterProxydeclaración, web.xmlpero puede tener varios filtros beanencadenados en el contexto de su aplicación.

Tahir Akhtar
fuente
muy bien explicado.
user4906240
15

El caso es que los filtros de servlets son administrados por el contenedor de servlets y no por resorte. Y es posible que deba inyectar algunos componentes de resorte en sus filtros.

Entonces, si necesita algo como:

public class FooFilter {

    @Inject
    private FooService service;

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

}

entonces necesitas el proxy de filtro delegado.

Bozho
fuente
1

Tienes razón sobre las cosas del 'pegamento'. Como está escrito en JavaDocs de FilterChainProxy :

FilterChainProxy se vincula a la cadena de filtros del contenedor de servlets agregando una declaración Spring DelegatingFilterProxy estándar en el archivo web.xml de la aplicación.

Consulte la sección FIlterChainProxy del blog Behind the Spring Security Namespace para obtener una excelente explicación.

Ritesh
fuente
0

Me ha dejado perplejo "springSecurityFilterChain" en web.xml y encontré esta respuesta en el documento de seguridad de springframework:

los <http> elemento encapsula la configuración de seguridad para la capa web de su aplicación. > Crea un bean FilterChainProxy llamado "springSecurityFilterChain" que mantiene la pila de> filtros de seguridad que componen la configuración de seguridad web [19]. Algunos filtros centrales siempre se> crean y otros se agregarán a la pila dependiendo de los atributos de los elementos secundarios que están> presentes. Las posiciones de los filtros estándar son fijas (consulte la tabla de orden de filtros en la> introducción del espacio de nombres), eliminando una fuente común de errores con versiones anteriores del marco> cuando los usuarios tenían que configurar la cadena de filtros explícitamente en el bean FilterChainProxy. Por supuesto, aún puede hacer esto si necesita un control total de la configuración.

Aquí está el enlace http://docs.spring.io/spring-security/site/docs/3.0.x/reference/appendix-namespace.html

Janet
fuente
0

Ha pasado mucho tiempo, pero tenía la misma pregunta y encontré esto: https://www.javacodegeeks.com/2013/11/spring-security-behind-the-scenes.html

Intenté ejecutar mi proyecto de seguridad de primavera quitando el filtro en cuestión y también agregándolo. Lo que encontré es que si agregamos el filtro, solo entonces la llamada se redirigirá a la página de inicio de sesión requerida como se define en la configuración de seguridad de primavera.

Por lo tanto, estoy de acuerdo con la respuesta de @ Ryan.

Fuera de quicio
fuente