Desarrollo de filtros de servlets para el proceso de inicio de sesión de formulario

Utilizando el mecanismo de inicio de sesión basado en formulario, puede controlar el diseño de la pantalla de inicio de sesión. En el inicio de sesión basado en formulario, debe especificar una página de inicio de sesión que se utiliza para recuperar la información sobre el ID de usuario y la contraseña. También se puede especificar una página de error que se visualice cuando la autenticación no sea correcta.

Acerca de esta tarea

Si se requiere una autenticación adicional o un proceso adicional antes y después de la autenticación, se pueden utilizar los filtros de servlets. Los filtros de servlets pueden utilizarse para interceptar de forma dinámica las solicitudes y las respuestas para transformar o utilizar la información contenida en las solicitudes o las respuestas. Uno o más filtros de servlets pueden adjuntarse a un servlet o a un grupo de servlets. Los filtros de servlets también se pueden adjuntar a archivos JSP y páginas HTML. Antes de invocar al servlet se llama a todos los filtros de servlets que se han adjuntado.

Tanto el filtro de servlet como el filtro de inicio de sesión basado en formulario reciben soporte en todos los contenedores Web que cumplan con la especificación de servlet versión 2.3. El servlet de inicio de sesión basado en formulario lleva a cabo la autenticación y los filtros de servlets pueden efectuar tareas adicionales de autenticación, auditoría o de registro cronológico de la información.

Para llevar a cabo acciones previas y posteriores al inicio de sesión con los filtros de servlet, configure estos filtros para que den soporte a la página de inicio de sesión basado en formulario o para el URL /j_security_check. El URL j_security_check se envía mediante una página de inicio de sesión basado en formulario con el parámetro j_username que contiene el nombre de usuario y el parámetro j_password que incluye la contraseña. Un filtro de servlet puede utilizar el parámetro de nombre de usuario y la información de contraseña para realizar otras tareas de autenticación o para otras necesidades especiales.

Procedimiento

  1. Un filtro de servlet implementa la clase javax.servlet.Filter. Hay tres métodos en la clase de filtro que es necesario implementar:
    • init(javax.servlet.FilterConfig cfg). Este método lo llama el contenedor una vez cuando el filtro de servlet entra en funcionamiento. El elemento FilterConfig que se pasa a este método contiene los init-parameters del filtro de servlet. Los init-parameters se pueden especificar para un filtro de servlets durante la configuración mediante la herramienta de ensamblaje.
    • destroy. Este método lo llama el contenedor cuando el filtro de servlets deja de funcionar.
    • doFilter(ServletRequest req, ServletResponse res, FilterChain chain). El contenedor llama a este método para cada solicitud de servlet correlacionada con este filtro antes de invocar el servlet. La cadena FilterChain que se pasa a este método puede utilizarse para invocar el filtro siguiente en la cadena de filtros. El servlet original solicitado se ejecuta cuando el último filtro de la cadena llama al método chain.doFilter. Por lo tanto, todos los filtros deben llamar al método chain.doFilter para poder ejecutar el servlet original después del filtrado. Si se implementa una comprobación de autenticación adicional en el código de filtro y se produce una anomalía, no es necesario ejecutar el servlet original. No se llama al método chain.doFilter y éste se puede redireccionar a alguna página de error diferente.
  2. Si un servlet se correlaciona con muchos filtros de servlets, se llama a los filtros de servlets en el orden en que se enumeran en el descriptor de despliegue web.xml de la aplicación. El archivo de clases de filtros de servlets debe colocarse en el directorio WEB-INF/classes de la aplicación.

Ejemplo

Un ejemplo de un filtro de servlet.

Este filtro de inicio de sesión puede correlacionarse con el URL /j_security_check para realizar acciones previas y posteriores al inicio de sesión.

import javax.servlet.*;
     public class LoginFilter implements Filter {
     protected FilterConfig filterConfig;
     // Se llama cuando se crea una instancia del filtro. 
     // Si se correlaciona con j_security_check, se llama 
     // la primera vez que se invoca j_security_check.
     public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
        }
     public void destroy() {
        this.filterConfig = null;
        }
      // Se llama por cada solicitud correlacionada a este filtro. 
     // Si se correlaciona con j_security_check, 
     // se llama para cada acción j_security_check
     public void doFilter(ServletRequest request, 
     ServletResponse response, FilterChain chain) 
         throws java.io.IOException, ServletException   {
         // efectuar aquí la acción previa al inicio de sesión
         chain.doFilter(request, response);  
         // llama al siguiente filtro de la cadena.  
         // j_security_check si este filtro 
         // se correlaciona con j_security_check.
        // efectuar aquí la acción posterior al inicio de sesión.
                 }
       }
Utilización de filtros de servlet para realizar procesos anteriores y posteriores al inicio de sesión durante el inicio de sesión de formularios

Este ejemplo ilustra un modo en que los filtros de servlet pueden realizar los procesos anteriores y posteriores al inicio de sesión durante el inicio de sesión de formularios.

Servlet filter source code: LoginFilter.java
/**
 * Ejemplo de filtro de servlet: Este ejemplo filtra j_security_check y
 * realiza acciones anteriores al inicio de sesión para determinar si el usuario que está intentando iniciar la sesión
 * está en la lista de revocados. Si el usuario está en la lista de revocados, se envía un error
 * al navegador.
 *
 * Este filtro lee el nombre de archivo de la lista de revocados en la FilterConfig 
 * que se pasa en el método init(). Lee el archivo de la lista de usuarios revocados y
 * crea una lista revokedUsers.
 * 
 * Cuando se llama al método doFilter, se comprueba el usuario que está iniciando la sesión 
 * para confirmar que éste usuario no está en la lista de usuarios revocados.
 *
 */

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*; 

public class LoginFilter implements Filter {

   protected FilterConfig filterConfig;

   java.util.List revokeList; 
   

   /**
    * init() : se llama al método init() cuando se crea una instancia del filtro.
    * Se crea una instancia de este filtro la primera vez que se invoca j_security_check para 
    * la aplicación (es decir, cuando se accede a un servlet protegido 
    * de la aplicación).
    */
   public void init(FilterConfig filterConfig) throws ServletException {
      this.filterConfig = filterConfig;

      // leer la lista de usuario revocados
      revokeList = new java.util.ArrayList(); 
      readConfig();
   }


   /**
    * destroy() : se llama al método destroy() cuando el filtro 
    * ya no está en servicio.
    */
   public void destroy() {
      this.filterConfig = null;
      revokeList = null;
   }

   /**
    * doFilter() : se llama al método doFilter() antes de que se invoque el servlet 
    * con el que está correlacionado este filtro. Dado que este filtro se  
    * correlaciona con j_security_check, se llama a este método antes de 
    * de que se envíe la acción j_security_check.
    */
   public void doFilter(ServletRequest request, ServletResponse response, 
FilterChain chain) throws java.io.IOException, ServletException {


      HttpServletRequest req = (HttpServletRequest)request;
      HttpServletResponse res = (HttpServletResponse)response;

      // acción de inicio de sesión previa
      
      // obtener nombre de usuario 
      String username = req.getParameter("j_username");

      // si el usuario está en la lista de revocados, enviar error
      if ( revokeList.contains(username) ) {
      res.sendError(javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED);
      return;
      }
      
      // llamar al siguiente filtro de la cadena: permitir que j_security_check autentique al 
      // usuario
      chain.doFilter(request, response);

      // acción de inicio de sesión posterior

   }

   /**
    * readConfig() : Lee el archivo de la lista de usuarios y crea una lista 
    * de usuarios revocada.
    */
   private void readConfig() {
      if ( filterConfig != null ) {

         // obtener el archivo de la lista de usuarios revocados y abrirlo.
         BufferedReader in;
         try { 
               String filename = filterConfig.getInitParameter("RevokedUsers");
               in = new BufferedReader( new FileReader(filename));
         } catch ( FileNotFoundException fnfe) {
               return;
         }
	
         // leer todos los usuarios revocados y añadirlos a revokeList. 
         String userName;
                  try {
               while ( (userName = in.readLine()) != null ) 
                   revokeList.add(userName);
         } catch (IOException ioe) {
         }

      }
  
   }

   
}
Importante: En el ejemplo de código anterior, la línea que empieza por public void doFilter(ServletRequest request se separa en dos sólo a efectos ilustrativos. La línea public void doFilter(ServletRequest request y la línea siguiente son una sola línea.
Ejemplo del archivo web.xml que muestra el filtro LoginFilter configurado y correlacionado con el URL j_security_check:
<filter id="Filter_1">
    <filter-name>LoginFilter</filter-name>
	   	   <filter-class>LoginFilter</filter-class>
	        	        <description>Realiza una operación previa y posterior al inicio de sesión</description>
			 <init-param>
			 			 <param-name>RevokedUsers</param-name>
			 			 <param-value>c:\WebSphere\AppServer\installedApps\
                            <app-name>\revokedUsers.lst</param-value>
				</init-param>
</filter-id>

<filter-mapping>
	<filter-name>LoginFilter</filter-name>
	    	    <url-pattern>/j_security_check</url-pattern>
</filter-mapping>
Ejemplo de un archivo de la lista de usuarios revocados:
user1
cn=user1,o=ibm,c=us
user99
cn=user99,o=ibm,c=us

Icon that indicates the type of topic Task topic



Timestamp icon Last updated: last_date
http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=tsec_servlet
File name: tsec_servlet.html