Esta es el arreglo más correcta que te podemos aportar, sin embargo estúdiala detenidamente y analiza si se adapta a tu proyecto.
Solución:
Chicos de Spring ayudaron de nuevo. Consulte https://github.com/spring-projects/spring-boot/issues/1640 y https://jira.spring.io/browse/SEC-2730
Spring Security no establece un orden en el filtro de bean que crea. Esto significa que, cuando Boot está creando un FilterRegistrationBean para él, obtiene el orden predeterminado que es LOWEST_PRECEDENCE.
Si desea que su propio filtro vaya tras el de Spring Security, puede crear su propio registro para el filtro de Spring Security y especificar el orden.
Entonces la respuesta a mi pregunta es:
@Bean
public FilterRegistrationBean securityFilterChain(@Qualifier(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME) Filter securityFilter)
FilterRegistrationBean registration = new FilterRegistrationBean(securityFilter);
registration.setOrder(Integer.MAX_VALUE - 1);
registration.setName(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME);
return registration;
@Bean
public FilterRegistrationBean userInsertingMdcFilterRegistrationBean()
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
UserInsertingMdcFilter userFilter = new UserInsertingMdcFilter();
registrationBean.setFilter(userFilter);
registrationBean.setOrder(Integer.MAX_VALUE);
return registrationBean;
Esto se solucionó en Spring Boot 1.2. La cadena de seguridad ahora está predeterminada en orden 0
.
También se puede establecer a través de propiedades:
security.filter-order=0 # Security filter chain order.
https://github.com/spring-projects/spring-boot/issues/1640
Aquí hay una respuesta compatible con Spring Boot 2 / Spring Security 5 que le permitirá insertar su filtro en un lugar arbitrario en la cadena de filtros.
Mi caso de uso fue un registro personalizado javax.servlet.Filter
que quería ejecutar antes de cualquier filtro de Spring Security; sin embargo, los pasos a continuación deberían permitirle colocar un filtro en cualquier lugar de su cadena de filtros Spring existente:
Paso 1: Averigüe el orden de los filtros Spring en su configuración actual.
Conecte su depurador remoto favorito a su aplicación y establezca un punto de interrupción en el doFilter(ServletRequest request, ServletResponse response)
método de org.springframework.security.web.FilterChainProxy
. A partir de Spring Security 5.1.6, esa es la línea 311. En su depurador, descubra los filtros existentes inspeccionando this.additionalFilters
. En mi aplicación, el orden era algo así como:
0: WebAsyncManagerIntegrationFilter
1: SecurityContextPersistenceFilter
2: HeaderWriterFilter
...
Paso 2: inserte su filtro en el lugar deseado usando WebSecurityConfigurerAdapter y HttpSecurity de Spring
Es probable que ya tengas un WebSecurityConfigurerAdapter
con un @Override configure(HttpSecurity http)
método. HttpSecurity
expone addFilterBefore
y addFilterAfter
métodos que le permiten colocar su filtro en relación con una clase existente en la cadena. Su filtro (instancia) es el primer argumento de estos métodos, y la clase del filtro que le gustaría insertar antes o después es el segundo argumento.
En mi caso, quería que mi filtro de registro personalizado fuera el primero en la cadena (mi fragmento de código es Kotlin, te dejo la implementación de Java):
override fun configure(http: HttpSecurity)
http
.addFilterBefore(MyCustomLoggingFilter(), WebAsyncManagerIntegrationFilter::class.java)
.authorizeRequests()
.antMatchers(
...
)
Paso 3: ¡Beneficio!
Utilice el método de depuración descrito en el Paso 1 anterior para verificar que su filtro se encuentra donde pretendía en la cadena de filtros.
Espero que esto ayude a alguien más por ahí.