En este ejercicio, vamos a implementar un sistema cliente-servidor en Java que permita gestionar usuarios, realizar autenticación, y validar sesiones. Este ejercicio está diseñado para ser un reto adecuado para un examen, ofreciendo una aplicación práctica de conceptos avanzados de programación en red y gestión de usuarios en Java.
Ejercicio: Implementación de un Servidor HTTP en Java con Gestión de Usuarios y Sesiones
Objetivo:
Desarrollar un servidor HTTP en Java que permita:
- Registro de usuarios: Un cliente puede registrarse con un nombre de usuario y una contraseña.
- Inicio de sesión: Un usuario registrado puede iniciar sesión proporcionando su nombre de usuario y contraseña.
- Gestión de sesiones: Si el inicio de sesión es exitoso, el servidor genera un token de sesión que el cliente utilizará para acceder a recursos protegidos.
- Validación de sesión: El cliente puede acceder a recursos protegidos utilizando el token de sesión.
Requisitos:
- Puerto de Escucha: El servidor debe escuchar en el puerto 8084.
- Registro de Usuarios: El cliente debe poder registrarse enviando su nombre de usuario y contraseña a la ruta
/register
mediante una solicitud POST. - Inicio de Sesión: El cliente debe poder iniciar sesión enviando su nombre de usuario y contraseña a la ruta
/login
mediante una solicitud POST. - Gestión de Sesiones: Si el inicio de sesión es exitoso, el servidor debe generar un token de sesión que se devolverá al cliente.
- Acceso a Recursos Protegidos: El cliente puede acceder a recursos protegidos enviando el token de sesión en la cabecera de la solicitud GET a la ruta
/protected
.
Solución en Java
A continuación, se presenta la implementación del servidor y el cliente en Java.
Parte 1: Implementación del Servidor HTTP
El servidor manejará la gestión de usuarios y la validación de sesiones.
package cristinaleonacademiaexamen;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.Executors;
import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
public class ServidorHTTP {
private static Map<String, String> usuarios = new HashMap<>();
private static Map<String, String> sesiones = new HashMap<>();
public static void main(String[] args) throws IOException {
HttpServer server = HttpServer.create(new InetSocketAddress(8084), 0);
server.createContext("/register", new RegistroHandler());
server.createContext("/login", new LoginHandler());
server.createContext("/protected", new RecursoProtegidoHandler());
server.setExecutor(Executors.newCachedThreadPool()); // Manejo concurrente de solicitudes
server.start();
System.out.println("Servidor HTTP iniciado en el puerto 8084");
}
static class RegistroHandler implements HttpHandler {
@Override
public void handle(HttpExchange exchange) throws IOException {
if ("POST".equals(exchange.getRequestMethod())) {
String[] credenciales = new String(exchange.getRequestBody().readAllBytes()).split("&");
String nombreUsuario = credenciales[0].split("=")[1];
String password = credenciales[1].split("=")[1];
if (usuarios.containsKey(nombreUsuario)) {
String respuesta = "Usuario ya registrado.";
exchange.sendResponseHeaders(409, respuesta.getBytes().length);
OutputStream os = exchange.getResponseBody();
os.write(respuesta.getBytes());
os.close();
} else {
usuarios.put(nombreUsuario, password);
String respuesta = "Usuario registrado con éxito.";
exchange.sendResponseHeaders(200, respuesta.getBytes().length);
OutputStream os = exchange.getResponseBody();
os.write(respuesta.getBytes());
os.close();
}
} else {
exchange.sendResponseHeaders(405, -1); // Método no permitido
}
}
}
static class LoginHandler implements HttpHandler {
@Override
public void handle(HttpExchange exchange) throws IOException {
if ("POST".equals(exchange.getRequestMethod())) {
String[] credenciales = new String(exchange.getRequestBody().readAllBytes()).split("&");
String nombreUsuario = credenciales[0].split("=")[1];
String password = credenciales[1].split("=")[1];
if (usuarios.containsKey(nombreUsuario) && usuarios.get(nombreUsuario).equals(password)) {
String token = UUID.randomUUID().toString();
sesiones.put(token, nombreUsuario);
String respuesta = "Inicio de sesión exitoso. Token de sesión: " + token;
exchange.sendResponseHeaders(200, respuesta.getBytes().length);
OutputStream os = exchange.getResponseBody();
os.write(respuesta.getBytes());
os.close();
} else {
String respuesta = "Credenciales incorrectas.";
exchange.sendResponseHeaders(401, respuesta.getBytes().length);
OutputStream os = exchange.getResponseBody();
os.write(respuesta.getBytes());
os.close();
}
} else {
exchange.sendResponseHeaders(405, -1); // Método no permitido
}
}
}
static class RecursoProtegidoHandler implements HttpHandler {
@Override
public void handle(HttpExchange exchange) throws IOException {
String token = exchange.getRequestHeaders().getFirst("Authorization");
if (sesiones.containsKey(token)) {
String nombreUsuario = sesiones.get(token);
String respuesta = "Acceso concedido al recurso protegido para el usuario: " + nombreUsuario;
exchange.sendResponseHeaders(200, respuesta.getBytes().length);
OutputStream os = exchange.getResponseBody();
os.write(respuesta.getBytes());
os.close();
} else {
String respuesta = "No autorizado. Token de sesión inválido.";
exchange.sendResponseHeaders(403, respuesta.getBytes().length);
OutputStream os = exchange.getResponseBody();
os.write(respuesta.getBytes());
os.close();
}
}
}
}
Explicación del Código:
- Gestión de Usuarios:
- Los usuarios se registran mediante la ruta
/register
, enviando un nombre de usuario y una contraseña. - El servidor almacena los usuarios en un
HashMap
.
- Inicio de Sesión y Generación de Tokens:
- La ruta
/login
permite a los usuarios iniciar sesión. Si las credenciales son correctas, el servidor genera un token de sesión único. - Este token se almacena en un
HashMap
junto con el nombre de usuario.
- Acceso a Recursos Protegidos:
- La ruta
/protected
verifica el token de sesión enviado por el cliente en la cabeceraAuthorization
. - Si el token es válido, el servidor concede acceso al recurso protegido.
Parte 2: Implementación del Cliente Java
El cliente interactuará con el servidor para registrar usuarios, iniciar sesión, y acceder a recursos protegidos utilizando el token de sesión.
Código del Cliente:
package cristinaleonacademiaexamen;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class ClienteHTTP {
public static void main(String[] args) {
try {
// Registro de usuario
String urlRegistro = "http://localhost:8084/register";
String credencialesRegistro = "usuario3=password3";
String respuestaRegistro = enviarSolicitudPost(urlRegistro, credencialesRegistro);
System.out.println("Respuesta del servidor (Registro): " + respuestaRegistro);
// Inicio de sesión
String urlLogin = "http://localhost:8084/login";
String credencialesLogin = "usuario3=password3";
String token = autenticarUsuario(urlLogin, credencialesLogin);
System.out.println("Token de sesión: " + token);
// Acceso a recurso protegido usando el token
String urlRecurso = "http://localhost:8084/protected";
String respuestaRecurso = accederRecursoProtegido(urlRecurso, token);
System.out.println("Respuesta del recurso protegido: " + respuestaRecurso);
} catch (Exception e) {
e.printStackTrace();
}
}
private static String enviarSolicitudPost(String urlStr, String datos) throws Exception {
URL url = new URL(urlStr);
HttpURLConnection conexion = (HttpURLConnection) url.openConnection();
conexion.setRequestMethod("POST");
conexion.setDoOutput(true);
try (OutputStream os = conexion.getOutputStream()) {
os.write(datos.getBytes());
os.flush();
}
BufferedReader in = new BufferedReader(new InputStreamReader(conexion.getInputStream()));
String inputLine;
StringBuilder contenido = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
contenido.append(inputLine);
}
in.close();
return contenido.toString();
}
private static String autenticarUsuario(String urlStr, String credenciales) throws Exception {
String respuesta = enviarSolicitudPost(urlStr, credenciales);
return extraerTokenDeRespuesta(respuesta);
}
private static String extraerTokenDeRespuesta(String respuesta) {
int inicio = respuesta.indexOf("Token de sesión: ") + 17;
return respuesta.substring(inicio);
}
private static String accederRecursoProtegido(String urlStr, String token) throws Exception {
URL url = new
URL(urlStr);
HttpURLConnection conexion = (HttpURLConnection) url.openConnection();
conexion.setRequestMethod("GET");
conexion.setRequestProperty("Authorization", token);
BufferedReader in = new BufferedReader(new InputStreamReader(conexion.getInputStream()));
String inputLine;
StringBuilder contenido = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
contenido.append(inputLine);
}
in.close();
return contenido.toString();
}
}
Explicación del Código:
- Registro de Usuarios:
- El cliente envía una solicitud POST al servidor con las credenciales del nuevo usuario. El servidor responde si el registro fue exitoso.
- Inicio de Sesión:
- El cliente envía las credenciales a la ruta
/login
. Si el inicio de sesión es exitoso, el servidor devuelve un token de sesión.
- Acceso a Recursos Protegidos:
- El cliente utiliza el token de sesión para acceder a un recurso protegido en el servidor. El token se envía en la cabecera
Authorization
.
- Métodos Auxiliares:
enviarSolicitudPost
: Envía una solicitud POST al servidor con los datos proporcionados.autenticarUsuario
: Gestiona el proceso de inicio de sesión y obtiene el token de sesión.accederRecursoProtegido
: Envía una solicitud GET al recurso protegido utilizando el token de sesión.
Conclusión
Este ejercicio avanzado implementa un sistema completo de gestión de usuarios y validación de sesiones en un entorno cliente-servidor en Java. Los usuarios pueden registrarse, iniciar sesión y acceder a recursos protegidos mediante tokens de sesión. Este ejercicio es ideal para un examen, ya que cubre conceptos clave de la programación en red, seguridad básica y la implementación de funcionalidades de gestión de sesiones en Java. ¡Espero que lo encuentres útil y desafiante!
¿QUÉ TE HA PARECIDO EL ARTÍCULO? Danos tu opinión al final de la página.
Deja tu comentario y ayúdanos a crecer.
¡SÍGUENOS EN TUS REDES FAVORITAS!
AYUDANOS A CRECER Y QUE LLEGUEMOS A TODAS LAS PERSONAS QUE NOS NECESITANA. SÍGUENOS EN TUS REDES.
Entra AQUÍ y elíge donde seguirnos.

NUESTRAS ÚLTIMAS PUBLICACIONES
- Las maravillas de las ciencias biológicas según la Academia SanRoque
- La motivación en Academia SanRoque
- Los docentes también se divierten.
- Comandos Principales en MongoDB y sus Equivalentes en Java
- Las bondades de escribir y leer cada día: herramientas esenciales para la vida académica, empresarial y social
- Immanuel Kant: Disertación contra las IA
- Forma Normal de Boyce-Codd (FNBC) en Bases de Datos
- Las Formas Normales en Bases de Datos
- La importancia de rodearte de personas virtuosas para alcanzar tus metas
ELIGE TU RED FAVORITA Y SÍGUENOS.
AYUDANOS A CRECER Y A LLEGAR A TODAS LAS PERSONAS QUE NOS NECESITAN.
Contenido restringido
Comments are closed