Implementación de Flujo de Autenticación y Despacho de Vistas con Servlets Java

La funcionalidad de inicio de sesión es una característica omnipresente en la mayoría de las aplicaciones web modernas. Una vez que un usuario se autentica correctamente, el sistema lo dirige a una página de destino, como un panel de usuario o una página de confirmación. Este artículo explora cómo construir un sistema básico de autenticación y redirección utilizando Servlets de Java, demostrando la captura de datos del formulario y el reenvío a una vista de éxito.

Diseño del Servlet de Procesamiento de Autenticación

El servlet será el componente central encargado de recibir y procesar la información enviada desde el formulario de inicio de sesión, como las credenciales del usuario y cualquier otro dato adicional, para luego gestionar la navegación del usuario hacia la vista apropiada.

package com.example.webapp;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet; // Anotación para mapear el servlet sin web.xml
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays; // Utilidad para imprimir arrays

@WebServlet("/autenticar") // Mapea este servlet a la URL /autenticar
public class GestorAutenticacionServlet extends HttpServlet {

    private static final long serialVersionUID = 1L; // ID de serialización

    @Override
    protected void doPost(HttpServletRequest solicitud, HttpServletResponse respuesta)
            throws ServletException, IOException {
        
        // Establecer la codificación de caracteres para evitar problemas con UTF-8
        solicitud.setCharacterEncoding("UTF-8");
        respuesta.setCharacterEncoding("UTF-8");

        // Extraer los parámetros del formulario HTML
        String nombreDeUsuario = solicitud.getParameter("nombreDeUsuario");
        String claveDeAcceso = solicitud.getParameter("claveDeAcceso");
        String[] preferenciasUsuario = solicitud.getParameterValues("preferencias");

        // Simulación de validación de credenciales (en un escenario real, se interactuaría con una capa de servicio/DAO)
        System.out.println("Solicitud de acceso - Usuario: " + nombreDeUsuario + ", Contraseña: " + claveDeAcceso);
        if (preferenciasUsuario != null && preferenciasUsuario.length > 0) {
            System.out.println("Preferencias seleccionadas: " + Arrays.toString(preferenciasUsuario));
        } else {
            System.out.println("El usuario no seleccionó preferencias.");
        }

        // Después de procesar, redirigir internamente a la página de éxito.
        // Utilizar RequestDispatcher.forward() mantiene los objetos de solicitud y respuesta.
        solicitud.getRequestDispatcher("/confirmacion-acceso.jsp").forward(solicitud, respuesta);
    }
    
    // El método doGet no está implementado para este ejemplo, ya que el formulario usa POST.
    // Si se intentara acceder vía GET, se invocaría el método de la superclase (HttpServlet),
    // que por defecto genera un error 405 (Method Not Allowed).
}

Formulario de Acceso de Usuario (index.jsp)

La siguiente página JSP proporciona la interfaz de usuario para que los usuarios ingresen sus datos antes de intentar iniciar sesión.

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <title>Acceso al Sistema</title>
    <style>
        body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 2em; background-color: #e0f2f7; display: flex; justify-content: center; align-items: center; min-height: 90vh; }
        .card-login { background-color: white; padding: 2.5em; border-radius: 10px; box-shadow: 0 4px 10px rgba(0,0,0,0.1); max-width: 450px; width: 100%; }
        h1 { text-align: center; color: #0277bd; margin-bottom: 1.5em; }
        .form-group { margin-bottom: 1.2em; }
        .form-group label { display: block; margin-bottom: 0.5em; font-weight: bold; color: #333; }
        .form-group input[type="text"], .form-group input[type="password"] { width: calc(100% - 22px); padding: 10px; border: 1px solid #b0bec5; border-radius: 5px; font-size: 1rem; }
        .form-group input[type="checkbox"] { margin-right: 8px; }
        .form-group .checkbox-options { display: flex; flex-wrap: wrap; gap: 15px; margin-top: 0.8em; }
        .form-group .checkbox-options label { font-weight: normal; color: #555; }
        button { background-color: #007bff; color: white; padding: 12px 20px; border: none; border-radius: 5px; cursor: pointer; font-size: 1.1rem; width: 100%; transition: background-color 0.3s ease; margin-top: 1.5em; }
        button:hover { background-color: #0056b3; }
    </style>
</head>
<body>
    <div class="card-login">
        <h1>Bienvenido, Inicie Sesión</h1>
        <form action="${pageContext.request.contextPath}/autenticar" method="post">
            <div class="form-group">
                <label for="nombreDeUsuario">Nombre de Usuario:</label>
                <input type="text" id="nombreDeUsuario" name="nombreDeUsuario" required>
            </div>
            <div class="form-group">
                <label for="claveDeAcceso">Contraseña:</label>
                <input type="password" id="claveDeAcceso" name="claveDeAcceso" required>
            </div>
            <div class="form-group">
                <label>Seleccione sus Preferencias:</label>
                <div class="checkbox-options">
                    <input type="checkbox" id="prefLibros" name="preferencias" value="Lectura"><label for="prefLibros">Lectura</label>
                    <input type="checkbox" id="prefCodificar" name="preferencias" value="Programacion"><label for="prefCodificar">Programación</label>
                    <input type="checkbox" id="prefPeliculas" name="preferencias" value="Cine"><label for="prefPeliculas">Cine</label>
                    <input type="checkbox" id="prefDeporte" name="preferencias" value="Deporte"><label for="prefDeporte">Deporte</label>
                </div>
            </div>
            <button type="submit">Acceder</button>
        </form>
    </div>
</body>
</html>

Página de Confirmación de Acceso (confirmacion-acceso.jsp)

Esta página se mostrará al usuario una vez que el servlet haya procesado el inicio de sesión con éxito.

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <title>Acceso Confirmado</title>
    <style>
        body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 2em; background-color: #e6ffe6; text-align: center; display: flex; justify-content: center; align-items: center; min-height: 90vh; }
        .success-card { background-color: white; padding: 2.5em; border-radius: 10px; box-shadow: 0 4px 10px rgba(0,0,0,0.1); max-width: 450px; width: 100%; border-left: 5px solid #28a745; }
        h1 { color: #28a745; margin-bottom: 0.8em; }
        p { font-size: 1.1em; color: #444; }
    </style>
</head>
<body>
    <div class="success-card">
        <h1>¡Inicio de Sesión Exitoso!</h1>
        <p>Ha accedido al sistema correctamente. ¡Bienvenido!</p>
    </div>
</body>
</html>

Configuración del Proyecto Maven

Para compilar y ejecutar esta aplicación web, se necesita un archivo pom.xml que defina las dependencias de la API de Servlets de Jakarta EE.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>webapp-simple-auth</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <jakarta.servlet.api.version>5.0.0</jakarta.servlet.api.version> <!-- Servlet 5.0 para Jakarta EE 9 -->
        <jakarta.servlet.jsp.api.version>3.0.0</jakarta.servlet.jsp.api.version> <!-- JSP 3.0 para Jakarta EE 9 -->
    </properties>

    <dependencies>
        <!-- API de Servlets de Jakarta EE -->
        <dependency>
            <groupId>jakarta.servlet</groupId>
            <artifactId>jakarta.servlet-api</artifactId>
            <version>${jakarta.servlet.api.version}</version>
            <scope>provided</scope> <!-- Suministrado por el contenedor de servlets (ej. Tomcat) -->
        </dependency>
        
        <!-- Opcional: API de JSP de Jakarta EE si se utilizan explícitamente etiquetas en un IDE -->
        <dependency>
            <groupId>jakarta.servlet.jsp</groupId>
            <artifactId>jakarta.servlet.jsp-api</artifactId>
            <version>${jakarta.servlet.jsp.api.version}</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!-- Plugin para la compilación de código fuente Java -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>${maven.compiler.source}</source>
                    <target>${maven.compiler.target}</target>
                </configuration>
            </plugin>
            <!-- Plugin para empaquetar el proyecto como un archivo WAR -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.3.2</version>
                <configuration>
                    <!-- Si se usan anotaciones para servlets, web.xml puede ser opcional -->
                    <failOnMissingWebXml>false</failOnMissingWebXml> 
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Aunque en este ejemplo se utiliza la anotación @WebServlet para el mapeo del servlet, también es posible configurar el servlet mediante el archivo web.xml. A continuación se muestra la configuración equivalente para web.xml, que puede ser utilizada si se prefiere un enfoque de despliegue descriptivo:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
                      https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
         version="5.0"> <!-- Usando la especificación Servlet 5.0 -->
    <servlet>
        <servlet-name>gestorAuth</servlet-name>
        <servlet-class>com.example.webapp.GestorAutenticacionServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>gestorAuth</servlet-name>
        <url-pattern>/autenticar</url-pattern>
    </servlet-mapping>
</web-app>

Este sistema de ejemplo ilustra un flujo fundamental para la interacción de usuarios en una aplicación web: capturar datos a través de un formulario, procesarlos en un servlet y, finalmente, mostrar una página de confirmación al usuario.

Etiquetas: java servlet jsp JakartaEE maven

Publicado el 6-12 21:43