Hola,
-
Has solicitado recuperar tu contraseña. Aquí está tu código de recuperación:
+
Has solicitado recuperar tu contraseña. Aquí está tu código:
$codigo
Este código expira en 10 minutos.
-
Si no solicitaste este código, por favor ignora este correo.
+
Si no lo solicitaste, ignora este mensaje.
© " . date('Y') . " SIIH · Desarrollado por AduanaSoft
@@ -159,11 +176,14 @@ function enviarCodigo()
$mail->send();
} catch (Exception $e) {
error_log("Error al enviar correo: {$mail->ErrorInfo}");
- die("❌ Hubo un error al enviar el correo. Intenta más tarde.");
+ echo json_encode(['success' => false, 'message' => '❌ Hubo un error al enviar el correo. Intenta más tarde.']);
+ exit;
}
- $_SESSION['email_recuperacion'] = $email;
- header('Location: /IMPORTADORES/login/verificarCodigoVista');
+ $_SESSION['email_recuperacion'] = $email; // email sin cifrar
+ $_SESSION['intentos_codigo'] = 0; // Inicializa intentos
+
+ echo json_encode(['success' => true, 'message' => '✅ Código enviado correctamente. Revisa tu correo.']);
exit;
}
@@ -174,33 +194,65 @@ function verificarCodigoVista()
function verificarCodigo()
{
+ header('Content-Type: application/json');
+
$conn = getConnection();
- $codigo = $_POST['codigo'] ?? '';
+
+ $codigo = trim($_POST['codigo'] ?? '');
$email = $_SESSION['email_recuperacion'] ?? '';
if (!$codigo || !$email) {
- die("❌ Código o correo faltante.");
+ echo json_encode(['success' => false, 'message' => '❌ Código o correo faltante.']);
+ exit;
}
// Encriptar el correo ingresado
$emailEncrypted = encrypt($email);
// Consultar el código de recuperación y su expiración desde la base de datos
- $sql = "SELECT codigo, expiracion FROM recuperacion_password WHERE email = ? ORDER BY id DESC";
+ $sql = "SELECT id, codigo, expiracion FROM recuperacion_password
+ WHERE email = ? AND estatus = 0 ORDER BY id DESC";
$stmt = sqlsrv_query($conn, $sql, [$emailEncrypted]);
-
$row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
- if (!$row || $codigo != $row['codigo']) {
- die("❌ Código incorrecto.");
+ if (!$row) {
+ echo json_encode(['success' => false, 'message' => '❌ Código no encontrado o ya usado.']);
+ exit;
}
- if (strtotime($row['expiracion']->format('Y-m-d H:i:s')) < time()) {
- die("⏰ El código ha expirado.");
+ // Manejo de intentos fallidos
+ $_SESSION['intentos_codigo'] = ($_SESSION['intentos_codigo'] ?? 0) + 1;
+ if ($_SESSION['intentos_codigo'] > 5) {
+ $update = "UPDATE recuperacion_password SET estatus = 1 WHERE id = ?";
+ sqlsrv_query($conn, $update, [$row['id']]);
+ unset($_SESSION['intentos_codigo']);
+ echo json_encode(['success' => false, 'message' => '🚫 Has excedido el número de intentos. Solicita un nuevo código.']);
+ exit;
}
- $_SESSION['recuperacion_autorizada'] = true;
- header('Location: /IMPORTADORES/login/cambiarPasswordVista');
+ if ($codigo != $row['codigo']) {
+ echo json_encode(['success' => false, 'message' => '❌ Código incorrecto. Intento {$_SESSION["intentos_codigo"]} de 5.']);
+ exit;
+ }
+
+ // Validar expiración
+ $expiracionTimestamp = strtotime($row['expiracion']->format('Y-m-d H:i:s'));
+ if ($expiracionTimestamp < time()) {
+ $update = "UPDATE recuperacion_password SET estatus = 1 WHERE id = ?";
+ sqlsrv_query($conn, $update, [$row['id']]);
+ echo json_encode(['success' => false, 'message' => '⏰ El código ha expirado.']);
+ exit;
+ }
+
+ // ✅ Código correcto
+ $update = "UPDATE recuperacion_password SET estatus = 1 WHERE id = ?";
+ sqlsrv_query($conn, $update, [$row['id']]);
+
+ // Habilitar cambio de contraseña
+ $_SESSION['recuperacion_autorizada'] = true;
+ unset($_SESSION['intentos_codigo']);
+
+ echo json_encode(['success' => true, 'message' => '✅ Código verificado. Redirigiendo...']);
exit;
}
@@ -219,7 +271,8 @@ function cambiarPasswordVista()
function cambiarPassword()
{
if (!isset($_SESSION['recuperacion_autorizada']) || !isset($_SESSION['email_recuperacion'])) {
- die("⚠️ Acceso no autorizado.");
+ echo "⚠️ Acceso no autorizado.";
+ return;
}
$conn = getConnection();
@@ -228,11 +281,13 @@ function cambiarPassword()
// Validaciones
if (strlen($password) < 6) {
- die("❌ La contraseña debe tener al menos 6 caracteres.");
+ echo "❌ La contraseña debe tener al menos 6 caracteres.";
+ return;
}
if ($password !== $confirmar) {
- die("❌ Las contraseñas no coinciden.");
+ echo "❌ Las contraseñas no coinciden.";
+ return;
}
$email = $_SESSION['email_recuperacion'];
@@ -246,10 +301,21 @@ function cambiarPassword()
$stmt = sqlsrv_prepare($conn, $sql, [$hash, $emailEncrypted]);
if (!$stmt || !sqlsrv_execute($stmt)) {
- die("❌ Error al actualizar la contraseña. Intenta nuevamente.");
+ echo "❌ Error al actualizar la contraseña. Intenta nuevamente.";
+ return;
}
- // Enviar correo de confirmación
+ // Obtener ID de usuario para registrar en bitácora
+ $sqlUsuario = "SELECT id_usuario FROM usuarios_sistema WHERE email = ?";
+ $stmtUsuario = sqlsrv_query($conn, $sqlUsuario, [$emailEncrypted]);
+ $usuario = sqlsrv_fetch_array($stmtUsuario, SQLSRV_FETCH_ASSOC);
+ $idUsuario = $usuario['id_usuario'] ?? null;
+
+ // Registrar en bitácora
+ $ip = $_SERVER['REMOTE_ADDR'] ?? 'N/A';
+ registrarBitacora($conn, $idUsuario, $email, $ip, 1, 'Cambio de contraseña por recuperación');
+
+ // Enviar correo de confirmación
try {
$mail = new PHPMailer(true);
@@ -290,6 +356,8 @@ function cambiarPassword()
$mail->send();
} catch (Exception $e) {
error_log("Error al enviar correo de confirmación: {$mail->ErrorInfo}");
+ echo "❌ Hubo un error al enviar el correo. Intenta más tarde.";
+ return;
// No se detiene el proceso si falla el correo
}
@@ -297,7 +365,13 @@ function cambiarPassword()
unset($_SESSION['recuperacion_autorizada']);
unset($_SESSION['email_recuperacion']);
- $_SESSION['login_success'] = 'Tu contraseña ha sido cambiada exitosamente. Inicia sesión.';
- header('Location: /IMPORTADORES/login');
- exit;
-}
+ // Mostrar mensaje de éxito y redirigir
+ echo "
+
✅ ¡Contraseña actualizada!
+
Tu contraseña ha sido cambiada exitosamente.
+
Serás redirigido al login en breve...
+
+ ";
+}
\ No newline at end of file
diff --git a/script_table.txt b/script_table.txt
index 5a7848e..9433ccd 100644
--- a/script_table.txt
+++ b/script_table.txt
@@ -3,4 +3,7 @@ CREATE TABLE recuperacion_password (
email NVARCHAR(255) NOT NULL,
codigo NVARCHAR(10) NOT NULL,
expiracion DATETIME NOT NULL
-);
\ No newline at end of file
+);
+
+ALTER TABLE recuperacion_password
+ADD estatus INT NOT NULL DEFAULT 0;
diff --git a/views/login/cambiar_password.php b/views/login/cambiar_password.php
index 9ffd7c9..c1af8d1 100644
--- a/views/login/cambiar_password.php
+++ b/views/login/cambiar_password.php
@@ -6,6 +6,11 @@ $color1 = explode(',', $config['colores_primarios'] ?? '#003366,#0055A5')
$color2 = explode(',', $config['colores_primarios'] ?? '#003366,#0055A5')[1];
$mantenimiento = $config['modo_mantenimiento'] ?? 0;
$mensajeMantenimiento = $config['mensaje_mantenimiento'] ?? 'El sistema se encuentra en mantenimiento temporal. Por favor, vuelve más tarde.';
+
+if (!isset($_SESSION['recuperacion_autorizada'])) {
+ header('Location: /IMPORTADORES/login');
+ exit;
+}
?>
@@ -119,31 +124,46 @@ $mensajeMantenimiento = $config['mensaje_mantenimiento'] ?? 'El sistema se encue
-
Cambiar contraseña
+
Cambiar contraseña
+
-
-
+
+
= $_SESSION['cambio_exito'] ?>
+
+
+