Filtros en Java EE: para que los usais mas alla de la autenticacion

Sergio
12 de Agosto del 2026

Con varios hilos por aquí de autenticación y sesiones en JSP/Servlets, un recordatorio de que los filtros (Filter) en Java EE/Jakarta EE dan mucho más juego que solo comprobar si el usuario ha iniciado sesión.

El caso básico que todo el mundo conoce, bloquear acceso sin sesión:

@WebFilter("/privado/*")
public class AutenticacionFilter implements Filter {
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpSession sesion = request.getSession(false);

        if (sesion == null || sesion.getAttribute("usuario") == null) {
            ((HttpServletResponse) res).sendRedirect("login.jsp");
            return;
        }
        chain.doFilter(req, res);
    }
}

Pero un filtro se ejecuta para cualquier petición que coincida con su patrón, antes de que llegue al servlet o JSP final, así que sirve para bastante más:

Logging centralizado: registrar cada petición (URL, tiempo de respuesta, usuario) en un único sitio, en vez de repetir código de log en cada servlet.

Forzar codificación de caracteres: un filtro que llama a request.setCharacterEncoding("UTF-8") antes de leer cualquier parámetro, para evitar los clásicos problemas de acentos/ñ que aparecen si no se fija la codificación a tiempo.

Comprimir la respuesta: un filtro que envuelve el OutputStream con GZIPOutputStream si el navegador acepta contenido comprimido (cabecera Accept-Encoding), sin tocar el código de cada servlet individual.

Cabeceras de seguridad: añadir Content-Security-Policy, X-Frame-Options u otras cabeceras a todas las respuestas desde un único punto, en vez de repetirlo en cada endpoint.

La idea de fondo: cualquier cosa que tenga que pasar «por todas o casi todas las peticiones» es candidata a filtro, en vez de repetir esa lógica al principio de cada servlet.

Sergio


Elena
12 de Agosto del 2026

Autenticación es el caso más citado, pero en proyectos reales acabo usando filtros para bastante más:

1. Logging/tiempo de respuesta: un filtro que envuelve cada petición, apunta el timestamp de entrada, deja pasar la petición al resto de la cadena, y al volver calcula cuánto tardó y lo registra. Es la forma más limpia de medir latencia de todos los endpoints sin tocar cada controlador uno a uno.

2. Compresión GZIP de la respuesta: un filtro que envuelve el ServletResponse con un stream que comprime al vuelo si el cliente indica soporte (Accept-Encoding: gzip), sin que ningún servlet individual tenga que preocuparse de eso.

3. Cabeceras CORS: centralizar en un único filtro la lógica de qué orígenes están permitidos y qué cabeceras se devuelven, en vez de repetirlo en cada endpoint que necesita ser llamado desde otro dominio.

4. Configuración de locale/i18n: un filtro que lee la cabecera Accept-Language (o un parámetro/cookie de preferencia del usuario) y fija el locale para el resto del procesamiento de esa petición, antes de que llegue a ningún servlet.

El patrón común en todos estos casos: algo que aplica a muchos o todos los endpoints por igual, y que si lo metieras dentro de cada servlet individual acabaría duplicado por todas partes. Esa es la señal de que encaja mejor como filtro que como código dentro del propio servlet.

Elena