Si en algún momento has trabajado con Spring Boot es probable que hayas escuchado sobre los «filters» que nos ofrece este framework. ¿Qué son realmente y para qué sirven?
Imagina un filtro como un agente de aduanas. Su función es interceptar todas solicitudes entrantes, examinar su contenido y realizar las verificaciones necesarias. Una vez comprobado que todo es correcto permite que la solicitud continúe su curso.
Una particularidad de los filtros es que puedes encadenar todos los que necesites, en el orden que necesites. 😉
¿Para que sirven?
Ahora que ya sabes lo que son los «filters» te estarás preguntando, ¿para que los necesito?
Lo cierto es que tienen muchos usos, siendo la autenticación y autorización el más común.
@Slf4j
@Component
public class AuthFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// Checks to auth user
log.info("Print from AuthFilter");
chain.doFilter(request, response);
}
}
Lenguaje del código: Java (java)
Aquí tenemos una implementación simple de un «filter» el cual se encargaría de autenticar el usuario que ha realizado la petición (no incluyo el código de autenticación ya que se sale del punto que se está explicando, si te interesa en un futuro hablaré de como conseguir esto con Spring Security).
¿Cómo tener varios filters?
Como he comentado antes, podemos tener varios «filters» encadenados y configurados para que se ejecuten en un orden concreto.
Ya hemos conseguido tener autenticación, pero ahora quiero tener otro «filter» para escribir en el log todas las peticiones recibidas. ¿Cómo podemos hacer esto?
@Slf4j
@Order(1)
@Component
public class LogFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// Checks to auth user
log.info("Print from LogFilter");
chain.doFilter(request, response);
}
}
Lenguaje del código: Java (java)
@Slf4j
@Order(2)
@Component
public class AuthFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// Checks to auth user
log.info("Print from AuthFilter");
chain.doFilter(request, response);
}
}
Lenguaje del código: Java (java)
Ahora tenemos dos «filters» cada uno con su responsabilidad. La anotación @Order nos sirve para indicar el orden de ejecución.
Existe la ligera posibilidad de que un «filter» se ejecute más de una vez, esto en muchos casos no supone un problema, pero si es algo que te preocupa Spring Boot nos ofrece una versión mejorada llamada OncePerRequestFilter que nos garantiza que se llamará una única vez por petición.
@Slf4j
@Order(2)
@Component
public class AuthFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
// Checks to auth user
log.info("Print from AuthFilter");
chain.doFilter(request, response);
}
}
Lenguaje del código: Java (java)
Filtros por URL
Los anteriores «filters» se ejecutan en todas las peticiones recibidas. ¿Y si queremos que solo se ejecuten para algunos endpoints específicos?
En este caso el «filter» será identico, solo tendrás que quitarle la anotación @Component que lo define como un bean y hace que se ejecute automáticamente. Ahora lo registraremos como bean de otra manera.
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<AuthFilter> authFilter(){
FilterRegistrationBean<AuthFilter> registrationBean
= new FilterRegistrationBean<>();
registrationBean.setFilter(new AuthFilter());
registrationBean.addUrlPatterns("/users/*");
registrationBean.setOrder(2);
return registrationBean;
}
}
Lenguaje del código: Java (java)
De esta forma registramos el «filter» que ya teníamos creado, pero solo se usará para las peticiones cuya URL empiece «/users/»
Si te interesa el código lo puedes ver en https://github.com/jgosmus/springboot-filter
Deja una respuesta