Proceso de Log In
Sábado 26 11:00 PM - Domingo 27 12:20 PM
Esta entrada del blog documentará una sola sesión intensa que duró desde el sábado por la noche hasta el domingo al mediodía. La meta fue implementar un sistema de login con lógica para bloquear IPs después de múltiples intentos fallidos, registrar eventos en la bitácora de la base de datos, y crear toda la integración backend/frontend. Aunque parecía una tarea relativamente sencilla, nos tomó más de 8 horas de tiempo programando debido a varios desafíos que surgieron.
Concepto inicial
Cada intento fallido de login se registrara en una tabla
BitacoraEvento.Después de 5 intentos fallidos en 30 minutos, la IP quedara bloqueada por 10 minutos.
Estos eventos quedarían reflejados en una tabla relacionada con
TipoEvento:2 = Login no exitoso.
3 = Login bloqueado (lockout).
Obstáculos que surgieron:
1. La columna id en
BitacoraEvento
Cuando intentamos registrar los eventos fallidos, recibimos un error:Cannot insert the value NULL into column 'id'...
Esto fue porque la columna
id no tenía configurado un IDENTITY(1,1) y esperaba que se le asignara manualmente un valor. No queríamos manejar manualmente las IDs, así que decidimos modificar la tabla para que el campo id se auto-generara. Esto nos ahorró muchos problemas.2. El error de conexión tras limpiar intentos fallidos
Después de implementar la limpieza de intentos fallidos cuando el bloqueo expiraba, comenzamos a recibir errores 500 que mostraban “Error de conexión” en el frontend. Esto nos tuvo un buen rato perdidos hasta que revisamos bien los logs y descubrimos que:
const checkLockoutRequest = new sql.Request(connection);
pero nunca se había inicializado
connection en esa parte del código. Un pequeño problema creado al tratar de reutilizar código ya creado en otras partes. La solución fue abrir la conexión una sola vez al principio del controlador y reutilizarla para todas las consultas.Descubrimos que, aunque el bloqueo (evento tipo 3) expiraba después de 10 minutos, los intentos fallidos (eventos tipo 2) seguían contando, porque no se limpiaban automáticamente. Esto provocaba que al siguiente intento el usuario se bloqueara de nuevo instantáneamente.
La solución fue limpiar los intentos fallidos cuando el bloqueo expiraba, asegurándonos de dar un "borrón y cuenta nueva" después de cada periodo de bloqueo.
Comentarios
Publicar un comentario