El filtro de servlets de Java se utiliza para interceptar la solicitud del cliente y realizar un preprocesamiento. También puede interceptar la respuesta y realizar un posprocesamiento antes de enviarla al cliente en la aplicación web. Este es el cuarto artículo de la serie Tutorial de aplicaciones web. Es posible que también desee consultar los artículos anteriores.
- Aplicación web Java
- Tutorial de servlets de Java
- Gestión de sesiones de servlets
Filtro de servlets
En este artículo, aprenderemos sobre el filtro de servlet en Java. Analizaremos varios usos del filtro de servlet, cómo podemos crear un filtro y aprenderemos a usarlo con una aplicación web simple.
-
¿Por qué tenemos Servlet Filter?
-
Interfaz de filtro de servlets
-
Anotación de Servlet WebFilter
-
Configuración del filtro de servlets en web.xml
-
Ejemplo de filtro de servlet para registro y validación de sesión
-
¿Por qué tenemos Servlet Filter?
En el último artículo, aprendimos cómo podemos administrar sesiones en aplicaciones web y si queremos asegurarnos de que un recurso sea accesible solo cuando la sesión del usuario sea válida, podemos lograrlo usando atributos de sesión de servlet. El enfoque es simple, pero si tenemos muchos servlets y jsps, será difícil de mantener debido al código redundante. Si queremos cambiar el nombre del atributo en el futuro, tendremos que cambiar todos los lugares donde tenemos autenticación de sesión. Es por eso que tenemos un filtro de servlet. Los filtros de servlet son componentes Java conectables que podemos usar para interceptar y procesar solicitudes antes de que se envíen a los servlets y la respuesta después de que el código del servlet esté terminado y antes de que el contenedor envíe la respuesta de regreso al cliente. Algunas tareas comunes que podemos hacer con los filtros de servlet son:
- Parámetros de solicitud de registro en archivos de registro.
- Autenticación y autorización de solicitud de recursos.
- Formateo del cuerpo o encabezado de la solicitud antes de enviarlo al servlet.
- Comprimir los datos de respuesta enviados al cliente.
- Modificar la respuesta agregando algunas cookies, información del encabezado, etc.
Como mencioné anteriormente, los filtros de servlet se pueden conectar y configurar en el archivo descriptor de implementación (web.xml). Los servlets y los filtros no se conocen entre sí y podemos agregar o eliminar un filtro de servlet simplemente editando web.xml. Podemos tener múltiples filtros para un solo recurso y podemos crear una cadena de filtros para un solo recurso en web.xml. Podemos crear un filtro de servlet implementando
javax.servlet.Filteruna interfaz. -
Interfaz de filtro de servlets
La interfaz de filtro de servlet es similar a la interfaz de servlet y necesitamos implementarla para crear nuestro propio filtro de servlet. La interfaz de filtro de servlet contiene los métodos de ciclo de vida de un filtro y es administrada por el contenedor de servlet. Los métodos de ciclo de vida de la interfaz de filtro de servlet son:
- void init(FilterConfig paramFilterConfig) : cuando el contenedor inicializa el filtro, este es el método que se invoca. Este método se llama solo una vez en el ciclo de vida del filtro y debemos inicializar todos los recursos en este método. El contenedor utiliza FilterConfig para proporcionar parámetros de inicialización y un objeto de contexto de servlet al filtro. Podemos generar una excepción ServletException en este método.
- doFilter(ServletRequest paramServletRequest, ServletResponse paramServletResponse, FilterChain paramFilterChain) : este es el método que invoca el contenedor cada vez que tiene que aplicar un filtro a un recurso. El contenedor proporciona referencias a objetos de solicitud y respuesta para filtrar como argumento. FilterChain se utiliza para invocar el siguiente filtro en la cadena. Este es un gran ejemplo del patrón de cadena de responsabilidad .
- void destroy() : cuando el contenedor descarga la instancia de Filter, invoca el método destroy(). Este es el método con el que podemos cerrar cualquier recurso abierto por Filter. Este método se llama solo una vez durante la vida útil de Filter.
-
Anotación de Servlet WebFilter
javax.servlet.annotation.WebFilterSe introdujo en Servlet 3.0 y podemos usar esta anotación para declarar un filtro de servlet. Podemos usar esta anotación para definir parámetros de inicio, nombre y descripción del filtro, servlets, patrones de URL y tipos de despachador para aplicar el filtro. Si realiza cambios frecuentes en las configuraciones del filtro, es mejor usar web.xml porque eso no requerirá que vuelva a compilar la clase de filtro. Lea : Tutorial de anotaciones de Java -
Configuración del filtro de servlets en web.xml
Podemos declarar un filtro de servlet en web.xml como se muestra a continuación.
filter filter-nameRequestLoggingFilter/filter-name !-- mandatory -- filter-classcom.journaldev.servlet.filters.RequestLoggingFilter/filter-class !-- mandatory -- init-param !-- optional -- param-nametest/param-name param-valuetestValue/param-value /init-param/filterPodemos asignar un filtro a clases de servlet o patrones de URL como se muestra a continuación.
filter-mapping filter-nameRequestLoggingFilter/filter-name !-- mandatory -- url-pattern/*/url-pattern !-- either url-pattern or servlet-name is mandatory -- servlet-nameLoginServlet/servlet-name dispatcherREQUEST/dispatcher/filter-mappingNota: Al crear la cadena de filtros para un servlet, el contenedor primero procesa los patrones de URL y luego los nombres de los servlets, por lo que si tiene que asegurarse de que los filtros se ejecuten en un orden particular, preste especial atención al definir la asignación de filtros. Los filtros de servlet se utilizan generalmente para solicitudes de clientes, pero a veces también queremos aplicar filtros con RequestDispatcher . En este caso, podemos utilizar el elemento despachador; los valores posibles son REQUEST, FORWARD, INCLUDE, ERROR y ASYNC. Si no se define ningún despachador, se aplica solo a las solicitudes de clientes.
-
Ejemplo de filtro de servlet para registro y validación de sesión
In our **servlet filter example**, we will create filters to log request cookies and parameters and validate session to all the resources except static HTMLs and LoginServlet because it will not have a session. We will create a dynamic web project **ServletFilterExample** whose project structure will look like the below image. [](https://journaldev.nyc3.cdn.digitaloceanspaces.com/2013/08/Servlet-Filter-Example-Project.png) login.html is the entry point of our application where the user will provide the login id and password for authentication. login.html code:```!DOCTYPE htmlhtmlheadmeta charset="US-ASCII"titleLogin Page/title/headbodyform action="LoginServlet" method="post"Username: input type="text" name="user"brPassword: input type="password" name="pwd"brinput type="submit" value="Login"/form/body/html```LoginServlet is used to authenticate the request from the client for login.```package com.journaldev.servlet.session;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.RequestDispatcher;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.Cookie;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;/** * Servlet implementation class LoginServlet */@WebServlet("/LoginServlet")public class LoginServlet extends HttpServlet {private static final long serialVersionUID = 1L;private final String userID = "admin";private final String password = "password";protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {// get request parameters for userID and passwordString user = request.getParameter("user");String pwd = request.getParameter("pwd");if(userID.equals(user) password.equals(pwd)){HttpSession session = request.getSession();session.setAttribute("user", "Pankaj");//setting session to expiry in 30 minssession.setMaxInactiveInterval(30*60);Cookie userName = new Cookie("user", user);userName.setMaxAge(30*60);response.addCookie(userName);response.sendRedirect("LoginSuccess.jsp");}else{RequestDispatcher rd = getServletContext().getRequestDispatcher("/login.html");PrintWriter out= response.getWriter();out.println("font color=redEither user name or password is wrong./font");rd.include(request, response);}}}```When the client is authenticated, it's forwarded to LoginSuccess.jsp LoginSuccess.jsp code:```%@ page language="java" contentType="text/html; charset=US-ASCII" pageEncoding="US-ASCII"%!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd"htmlheadmeta http-equiv="Content-Type" content="text/html; charset=US-ASCII"titleLogin Success Page/title/headbody%//allow access only if session existsString user = (String) session.getAttribute("user");String userName = null;String sessionID = null;Cookie[] cookies = request.getCookies();if(cookies !=null){for(Cookie cookie : cookies){if(cookie.getName().equals("user")) userName = cookie.getValue();if(cookie.getName().equals("JSESSIONID")) sessionID = cookie.getValue();}}%h3Hi %=userName %, Login successful. Your Session ID=%=sessionID %/h3brUser=%=user %bra href="CheckoutPage.jsp"Checkout Page/aform action="LogoutServlet" method="post"input type="submit" value="Logout" /form/body/html```Notice that there is no session validation logic in the above JSP. It contains a link to another JSP page, CheckoutPage.jsp. CheckoutPage.jsp code:```%@ page language="java" contentType="text/html; charset=US-ASCII" pageEncoding="US-ASCII"%!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd"htmlheadmeta http-equiv="Content-Type" content="text/html; charset=US-ASCII"titleLogin Success Page/title/headbody%String userName = null;String sessionID = null;Cookie[] cookies = request.getCookies();if(cookies !=null){for(Cookie cookie : cookies){if(cookie.getName().equals("user")) userName = cookie.getValue();}}%h3Hi %=userName %, do the checkout./h3brform action="LogoutServlet" method="post"input type="submit" value="Logout" /form/body/html```LogoutServlet is invoked when a client clicks on the Logout button in any of the JSP pages.```package com.journaldev.servlet.session;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.Cookie;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;/** * Servlet implementation class LogoutServlet */@WebServlet("/LogoutServlet")public class LogoutServlet extends HttpServlet {private static final long serialVersionUID = 1L; protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); Cookie[] cookies = request.getCookies(); if(cookies != null){ for(Cookie cookie : cookies){ if(cookie.getName().equals("JSESSIONID")){ System.out.println("JSESSIONID="+cookie.getValue()); break; } } } //invalidate the session if exists HttpSession session = request.getSession(false); System.out.println("User="+session.getAttribute("user")); if(session != null){ session.invalidate(); } response.sendRedirect("login.html"); }}```Now we will create logging and authentication servlet filter classes.```package com.journaldev.servlet.filters;import java.io.IOException;import java.util.Enumeration;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletContext;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.annotation.WebFilter;import javax.servlet.http.Cookie;import javax.servlet.http.HttpServletRequest;/** * Servlet Filter implementation class RequestLoggingFilter */@WebFilter("/RequestLoggingFilter")public class RequestLoggingFilter implements Filter {private ServletContext context;public void init(FilterConfig fConfig) throws ServletException {this.context = fConfig.getServletContext();this.context.log("RequestLoggingFilter initialized");}public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {HttpServletRequest req = (HttpServletRequest) request;EnumerationString params = req.getParameterNames();while(params.hasMoreElements()){String name = params.nextElement();String value = request.getParameter(name);this.context.log(req.getRemoteAddr() + "::Request Params::{"+name+"="+value+"}");}Cookie[] cookies = req.getCookies();if(cookies != null){for(Cookie cookie : cookies){this.context.log(req.getRemoteAddr() + "::Cookie::{"+cookie.getName()+","+cookie.getValue()+"}");}}// pass the request along the filter chainchain.doFilter(request, response);}public void destroy() {//we can close resources here}}``````package com.journaldev.servlet.filters;import java.io.IOException;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletContext;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.annotation.WebFilter;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;@WebFilter("/AuthenticationFilter")public class AuthenticationFilter implements Filter {private ServletContext context;public void init(FilterConfig fConfig) throws ServletException {this.context = fConfig.getServletContext();this.context.log("AuthenticationFilter initialized");}public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {HttpServletRequest req = (HttpServletRequest) request;HttpServletResponse res = (HttpServletResponse) response;String uri = req.getRequestURI();this.context.log("Requested Resource::"+uri);HttpSession session = req.getSession(false);if(session == null !(uri.endsWith("html") || uri.endsWith("LoginServlet"))){this.context.log("Unauthorized access request");res.sendRedirect("login.html");}else{// pass the request along the filter chainchain.doFilter(request, response);}}public void destroy() {//close any resources here}}```Notice that we are not authenticating any HTML page or LoginServlet. Now we will configure these filters mapping in the web.xml file.```?xml version="1.0" encoding="UTF-8"?web-app xmlns_xsi="https://www.w3.org/2001/XMLSchema-instance" xsi_schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0" display-nameServletFilterExample/display-name welcome-file-list welcome-filelogin.html/welcome-file /welcome-file-list filter filter-nameRequestLoggingFilter/filter-name filter-classcom.journaldev.servlet.filters.RequestLoggingFilter/filter-class /filter filter filter-nameAuthenticationFilter/filter-name filter-classcom.journaldev.servlet.filters.AuthenticationFilter/filter-class /filter filter-mapping filter-nameRequestLoggingFilter/filter-name url-pattern/*/url-pattern dispatcherREQUEST/dispatcher /filter-mapping filter-mapping filter-nameAuthenticationFilter/filter-name url-pattern/*/url-pattern /filter-mapping/web-app```Now when we will run our application, we will get response pages like below images. [](https://journaldev.nyc3.cdn.digitaloceanspaces.com/2013/08/Servlet-Filter-Login.png) [](https://journaldev.nyc3.cdn.digitaloceanspaces.com/2013/08/Servlet-Filter-Login-Success.png) [](https://journaldev.nyc3.cdn.digitaloceanspaces.com/2013/08/Servlet-Filter-Checkout.png) If you are not logged in and try to access any JSP page, you will be forwarded to the login page. In the server log file, you can see the logs written by servlet filters as well as servlets.```Aug 13, 2013 1:06:07 AM org.apache.catalina.core.ApplicationContext logINFO: 0:0:0:0:0:0:0:1%0::Cookie::{JSESSIONID,B7275762B8D23121152B1270D6EB240A}Aug 13, 2013 1:06:07 AM org.apache.catalina.core.ApplicationContext logINFO: Requested Resource::/ServletFilterExample/Aug 13, 2013 1:06:07 AM org.apache.catalina.core.ApplicationContext logINFO: Unauthorized access requestAug 13, 2013 1:06:07 AM org.apache.catalina.core.ApplicationContext logINFO: 0:0:0:0:0:0:0:1%0::Cookie::{JSESSIONID,B7275762B8D23121152B1270D6EB240A}Aug 13, 2013 1:06:07 AM org.apache.catalina.core.ApplicationContext logINFO: Requested Resource::/ServletFilterExample/login.htmlAug 13, 2013 1:06:43 AM org.apache.catalina.core.ApplicationContext logINFO: 0:0:0:0:0:0:0:1%0::Request Params::{pwd=password}Aug 13, 2013 1:06:43 AM org.apache.catalina.core.ApplicationContext logINFO: 0:0:0:0:0:0:0:1%0::Request Params::{user=admin}Aug 13, 2013 1:06:43 AM org.apache.catalina.core.ApplicationContext logINFO: 0:0:0:0:0:0:0:1%0::Cookie::{JSESSIONID,B7275762B8D23121152B1270D6EB240A}Aug 13, 2013 1:06:43 AM org.apache.catalina.core.ApplicationContext logINFO: Requested Resource::/ServletFilterExample/LoginServletAug 13, 2013 1:06:43 AM org.apache.catalina.core.ApplicationContext logINFO: 0:0:0:0:0:0:0:1%0::Cookie::{JSESSIONID,8BDF777933194EDCAC1D8F1B73633C56}Aug 13, 2013 1:06:43 AM org.apache.catalina.core.ApplicationContext logINFO: 0:0:0:0:0:0:0:1%0::Cookie::{user,admin}Aug 13, 2013 1:06:43 AM org.apache.catalina.core.ApplicationContext logINFO: Requested Resource::/ServletFilterExample/LoginSuccess.jspAug 13, 2013 1:06:52 AM org.apache.catalina.core.ApplicationContext logINFO: 0:0:0:0:0:0:0:1%0::Cookie::{JSESSIONID,8BDF777933194EDCAC1D8F1B73633C56}Aug 13, 2013 1:06:52 AM org.apache.catalina.core.ApplicationContext logINFO: 0:0:0:0:0:0:0:1%0::Cookie::{user,admin}Aug 13, 2013 1:06:52 AM org.apache.catalina.core.ApplicationContext logINFO: Requested Resource::/ServletFilterExample/CheckoutPage.jspAug 13, 2013 1:07:00 AM org.apache.catalina.core.ApplicationContext logINFO: 0:0:0:0:0:0:0:1%0::Cookie::{JSESSIONID,8BDF777933194EDCAC1D8F1B73633C56}Aug 13, 2013 1:07:00 AM org.apache.catalina.core.ApplicationContext logINFO: 0:0:0:0:0:0:0:1%0::Cookie::{user,admin}Aug 13, 2013 1:07:00 AM org.apache.catalina.core.ApplicationContext logINFO: Requested Resource::/ServletFilterExample/LogoutServletJSESSIONID=8BDF777933194EDCAC1D8F1B73633C56User=PankajAug 13, 2013 1:07:00 AM org.apache.catalina.core.ApplicationContext logINFO: 0:0:0:0:0:0:0:1%0::Cookie::{JSESSIONID,8BDF777933194EDCAC1D8F1B73633C56}Aug 13, 2013 1:07:00 AM org.apache.catalina.core.ApplicationContext logINFO: 0:0:0:0:0:0:0:1%0::Cookie::{user,admin}Aug 13, 2013 1:07:00 AM org.apache.catalina.core.ApplicationContext logINFO: Requested Resource::/ServletFilterExample/login.htmlAug 13, 2013 1:07:06 AM org.apache.catalina.core.ApplicationContext logINFO: 0:0:0:0:0:0:0:1%0::Cookie::{JSESSIONID,8BDF777933194EDCAC1D8F1B73633C56}Aug 13, 2013 1:07:07 AM org.apache.catalina.core.ApplicationContext logINFO: 0:0:0:0:0:0:0:1%0::Cookie::{user,admin}Aug 13, 2013 1:07:07 AM org.apache.catalina.core.ApplicationContext logINFO: Requested Resource::/ServletFilterExample/LoginSuccess.jspAug 13, 2013 1:07:07 AM org.apache.catalina.core.ApplicationContext logINFO: Unauthorized access requestAug 13, 2013 1:07:07 AM org.apache.catalina.core.ApplicationContext logINFO: 0:0:0:0:0:0:0:1%0::Cookie::{JSESSIONID,8BDF777933194EDCAC1D8F1B73633C56}Aug 13, 2013 1:07:07 AM org.apache.catalina.core.ApplicationContext logINFO: 0:0:0:0:0:0:0:1%0::Cookie::{user,admin}Aug 13, 2013 1:07:07 AM org.apache.catalina.core.ApplicationContext logINFO: Requested Resource::/ServletFilterExample/login.html```
Eso es todo sobre el filtro de servlets en Java. Es una de las características importantes de las aplicaciones web Java EE y deberíamos utilizarla para tareas comunes realizadas por varios servlets. En futuras publicaciones, analizaremos los oyentes de servlets y las cookies. Actualización: después de recibir muchas solicitudes para el proyecto descargable, lo adjunté a la publicación; descárguelo desde el siguiente enlace.
Descargar Proyecto de ejemplo de filtro de servlet
Consulte el próximo artículo de la serie sobre Servlet Listener . Actualización Struts 2 utiliza Servlet Filter para interceptar las solicitudes de los clientes y reenviarlas a las clases de acción adecuadas, que se denominan Struts 2 Interceptors. Consulte el Tutorial para principiantes de Struts 2 .