Esta sección analiza la arquitectura de alto nivel de Spring Security en aplicaciones basadas en servlets.
Una breve descripción de los filtros
El soporte de servlet de Spring Security se basa en instancias de servlet Filter
, por lo que es útil observar primero la función de Filter
en general. La siguiente figura muestra una estructura en capas típica de controladores para una única solicitud HTTP.

El cliente envía una solicitud a la aplicación y el contenedor crea un FilterChain
, que contiene instancias de un Filter
y un Servlet
que deben procesar un HttpServletRequest
según la ruta del URI de solicitud. En una aplicación Spring MVC, Servlet
es una instancia de DispatcherServlet
. Sólo un Servlet
puede manejar una HttpServletRequest
y una HttpServletResponse
. Sin embargo, puede utilizar más de un filtro
para:
evitar llamadas al
filtro
o al descendenteservlet
. En este caso,Filter
normalmente registraHttpServletResponse
.Cambios en
HttpServletRequest
oHttpServletResponse
utilizado por los subsiguientesFilter
yServlet
El poder de Filter
depende de FilterChain
, que se le pasa.
FilterChain
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
// hacer algo antes de ejecutar el resto de la cadena de aplicaciones
chain.doFilter(request, response); // invocar el resto de la aplicación
// hacer algo después de ejecutar el resto de la aplicación
}
fun doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) {
// hacer algo antes de ejecutar el resto de la aplicación
chain.doFilter(request, response); // invocar el resto de la aplicación
// hacer algo después el resto de la aplicación se ha ejecutado
}
Porque el Filtro
solo afecta al subyacente Filtro
y Servlet
, el orden en el que se llama a cada Filter
es extremadamente importante.
DelegatingFilterProxy
Spring proporciona un implementación de Filter
titulado DelegatingFilterProxy
, que le permite establecer un puente entre el ciclo de vida de un contenedor de servlets y ApplicationContext
de Spring. El contenedor de servlets le permite registrar instancias Filter
utilizando sus propios estándares, pero no conoce los beans definidos por Spring. DelegatingFilterProxy
se puede registrar a través de mecanismos de contenedor de servlets estándar, pero delega todo el trabajo al Spring Bean que implementa Filter
.
Así es como DelegatingFilterProxy
se utiliza encaja en un esquema con instancias Filter
y FilterChain
.

DelegatingFilterProxy
busca Bean Filter0 en ApplicationContext
y luego llama a Bean Filter0. El pseudocódigo para DelegatingFilterProxy
se muestra a continuación.
DelegatingFilterProxy
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
// En modo diferido, obtenemos el filtro que se registró como Spring bean
// Para el ejemplo en DelegatingFilterProxy, el delegado es la instancia Bean Filter0
Filter delegate = getFilterBean(someBeanName);
// delega el trabajo al Spring Bean delegado.doFilter(solicitud, respuesta);
}
fun doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) {
// En modo diferido, obtenemos el filtro que se registró como Spring Bean
// Para el ejemplo en DelegatingFilterProxy, el delegado es una instancia de Bean Filter0
val delegate: Filter = getFilterBean(someBeanName)
// delegar el trabajo con Spring Bean delegado.doFilter(solicitud, respuesta)
}
Otra ventaja de DelegatingFilterProxy
es que le permite diferir la búsqueda de instancias de beans Filter
. Esto es importante porque el contenedor necesita registrar instancias Filter
antes de ejecutarlo. Sin embargo, Spring normalmente usa ContextLoaderListener
para cargar Spring beans, lo que solo ocurre después de que se hayan registrado las instancias Filter
.
FilterChainProxy
Las instalaciones de servlet en Spring Security están contenidas en FilterChainProxy
. FilterChainProxy
es un Filter
especializado proporcionado por Spring Security que le permite delegar autoridad a múltiples instancias de Filter
a través de SecurityFilterChain
. Dado que FilterChainProxy
es un bean, generalmente está incluido en DelegatingFilterProxy.

SecurityFilterChain
SecurityFilterChain
es utilizado por FilterChainProxy para determinar qué Filter
de Spring Security debe llamarse para una solicitud determinada.

Los filtros de seguridad en SecurityFilterChain
suelen ser beans, pero están registrados en FilterChainProxy
en lugar de DelegatingFilterProxy
. FilterChainProxy
proporciona varias ventajas sobre el registro directo con el contenedor de servlets o DelegatingFilterProxy. Primero, proporciona el punto de partida para todo el soporte de servlets en Spring Security. Por este motivo, si está intentando solucionar problemas de compatibilidad con servlets de Spring Security, un buen lugar para comenzar es agregar un punto de depuración a FilterChainProxy
.
En segundo lugar, porque FilterChainProxy
es fundamental para el uso de Spring Security, puede realizar tareas que no se consideran opcionales. Por ejemplo, limpia SecurityContext
para evitar pérdidas de memoria. También utiliza HttpFirewall
de Spring Security para proteger las aplicaciones de ciertos tipos de ataques.
También proporciona mayor flexibilidad para determinar cuándo llamar a SecurityFilterChain
. En un contenedor de servlets, las instancias Filter
se llaman basándose únicamente en la URL. Sin embargo, FilterChainProxy
puede determinar la llamada basándose en cualquier cosa en HttpServletRequest
usando la interfaz RequestMatcher
.
De hecho, FilterChainProxy
se puede utilizar para determinar qué SecurityFilterChain
se debe utilizar. Esto le permite proporcionar una configuración completamente separada para diferentes partes de su aplicación.

En la imagen con varios SecurityFilterChain, el FilterChainProxy
La instancia decide qué SecurityFilterChain
debe usarse. Sólo se llamará al primer SecurityFilterChain
coincidente. Si se solicita la URL /api/messages/
, primero se comparará con el patrón SecurityFilterChain0
a través de /api/* *
, por lo que solo se llamará SecurityFilterChain0
, incluso si también coincide con SecurityFilterChainn
. Si se solicita la URL /messages/
, no se comparará con el patrón SecurityFilterChain0
a través de /api/**
, por lo que FilterChainProxy
continuará iterando sobre cada SecurityFilterChain
. Se supone que no se llamarán otras instancias de SecurityFilterChain
que coincidan con SecurityFilterChainn
.
Tenga en cuenta que en SecurityFilterChain0
solo se configuran tres instancias de Filter
. Sin embargo, hay cuatro Filter
configurados en SecurityFilterChainn
. Es importante tener en cuenta que cada SecurityFilterChain
puede ser única y configurarse de forma aislada. De hecho, SecurityFilterChain
puede tener cero instancias de Filter
si la aplicación quiere que Spring Security ignore ciertas solicitudes.
Filtros de seguridad
Los filtros Spring Security se agregan a FilterChainProxy a través de la API SecurityFilterChain. El orden de las instancias de Filter
es importante. Normalmente no es necesario conocer el orden de Filter
en Spring Security. Sin embargo, en algunos casos es útil saber en qué orden están.
La siguiente es una lista ordenada completa de los filtros Spring Security:
ForceEagerSessionCreationFilter
ChannelProcessingFilter
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
CorsFilter
CsrfFilter
LogoutFilter
OAuth2AuthorizationRequestRedirectFilter
Saml2WebSsoAuthenticationRequestFilter
X509AuthenticationFilter
AbstractPreAuthenticatedProcessingFilter
CasAuthenticationFilter
OAuth2LoginAuthenticationFilter
Saml2WebSsoAuthenticationFilter
Nombre de usuarioContraseñaAuthenticationFilter
OpenIDAuthenticationFilter
DefaultLoginPageGeneratingFilter
DefaultLogoutPageGeneratingFilter
ConcurrentSessionFilter
DigestAuthenticationFilter
BearerTokenAuthenticationFilter
BasicAuthenticationFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
JaasApiIntegrationFilter
RememberMeAuthenticationFilter
AnonymousAuthenticationFilter
OAuth2AuthorizationCodeGrantFilter
SessionManagementFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
SwitchUserFilter
Manejo de excepciones de seguridad
ExceptionTranslationFilter
permite la conversión AccessDeniedException
y AuthenticationException
en las respuestas HTTP.
ExceptionTranslationFilter
se agrega a FilterChainProxy en calidad de uno de los filtros de seguridad.

1 El primer
ExceptionTranslationFilter
accede aFilterChain.doFilter(solicitud, respuesta)
para llamar al resto de la aplicación.2 Si el usuario no está autenticado o se produce una
AuthenticationException
ocurre, luego ejecute procedimiento de autenticación.TheSecurityContextHolder se borra
HttpServletRequest
se guarda en el destinoSolicitarCaché
. Una vez que el usuario se haya autenticado correctamente, se utilizaráRequestCache
para reproducir la solicitud original.AuthenticationEntryPoint
se utilizará para solicitar credenciales de datos del cliente. Por ejemplo, podría redirigir a una página de inicio de sesión o enviar un encabezadoWWW-Authenticate
.
3 De lo contrario, si se produce
AccessDeniedException
, se denegará el acceso.AccessDeniedHandle
r
se llama para manejar la denegación de acceso.
Si la aplicación no genera una AccessDeniedException
o una AuthenticationException
, entonces el ExceptionTranslationFilter
no hace nada.
El pseudocódigo para ExceptionTranslationFilter
se parece a esto:
try {
filterChain.doFilter(request, response);
} catch (AccessDeniedException | AuthenticationException ex) {
if (!authenticated || ex instanceof AuthenticationException) {
startAuthentication();
} else {
accessDenied();
}
}
- De la breve descripción de las instancias de
Filter
, puede recordar que llamar aFilterChain.doFilter(solicitud, respuesta)
es equivalente a llamar al resto de la aplicación. significa que si otra parte de la aplicación (por ejemplo,FilterSecurityInterceptor
o método de seguridad) genera unaAuthenticationException
oAccessDeniedException
, entonces esas excepciones serán detectadas y manejadas. en esta etapa. - Si el usuario no está autenticado o se genera una
AuthenticationException
, entonces ejecute el procedimiento de autenticación. - De lo contrario se denegará el acceso
GO TO FULL VERSION