procesar_login.php Controlador de login (bcrypt + CSRF) 1 líneas
1
<?php
// ============================================================
// SIDE - ARC 1.0
// Archivo: procesar_login.php
// Propósito: Procesa el formulario POST de login. Valida
//            credenciales contra la BD usando password_verify().
//            No genera HTML propio: solo redirige.
// ============================================================

if (session_status() === PHP_SESSION_NONE) {
    session_start();
}

// --- Solo acepta método POST ---
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    header('Location: /apps/side-arc/index.php');
    exit;
}

// --- Validar token CSRF ---
if (
    empty($_POST['csrf_token']) ||
    empty($_SESSION['csrf_token']) ||
    !hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])
) {
    $_SESSION['login_error'] = 'Solicitud inválida. Intente de nuevo.';
    header('Location: /apps/side-arc/login.php');
    exit;
}

// Invalidar token CSRF tras uso (one-time token)
unset($_SESSION['csrf_token']);

// --- Sanitizar entradas ---
$usuario_input  = trim($_POST['usuario']  ?? '');
$password_input = trim($_POST['password'] ?? '');

// --- Validar que no estén vacíos ---
if (empty($usuario_input) || empty($password_input)) {
    $_SESSION['login_error'] = 'El usuario y la contraseña son obligatorios.';
    header('Location: /apps/side-arc/login.php');
    exit;
}

// --- Conectar a la base de datos ---
require_once 'conexion.php';

// --- Buscar usuario en la BD (solo usuarios activos) ---
// Usamos prepared statement para prevenir SQL Injection
$stmt = mysqli_prepare(
    $conexion,
    "SELECT id, nombre, password_hash FROM usuarios
     WHERE usuario = ? AND activo = 1 LIMIT 1"
);

if (!$stmt) {
    $_SESSION['login_error'] = 'Error interno del sistema. Intente más tarde.';
    header('Location: /apps/side-arc/login.php');
    exit;
}

mysqli_stmt_bind_param($stmt, 's', $usuario_input);
mysqli_stmt_execute($stmt);
$resultado = mysqli_stmt_get_result($stmt);
$usuario_bd = mysqli_fetch_assoc($resultado);
mysqli_stmt_close($stmt);
mysqli_close($conexion);

// --- Verificar contraseña con bcrypt ---
// Mensaje de error genérico para no revelar si el usuario existe
$error_generico = 'Usuario o contraseña incorrectos.';

if (!$usuario_bd) {
    // Usuario no encontrado — simular tiempo de hash para
    // prevenir ataques de temporización (timing attacks)
    password_verify('dummy_password', '$2y$12$invalid.hash.padding.here.xxxxx');
    $_SESSION['login_error'] = $error_generico;
    header('Location: /apps/side-arc/login.php');
    exit;
}

if (!password_verify($password_input, $usuario_bd['password_hash'])) {
    $_SESSION['login_error'] = $error_generico;
    header('Location: /apps/side-arc/login.php');
    exit;
}

// --- Credenciales correctas: regenerar ID de sesión ---
// Previene Session Fixation attacks
session_regenerate_id(true);

// --- Guardar datos del administrador en sesión ---
$_SESSION['admin_id']     = (int) $usuario_bd['id'];
$_SESSION['admin_nombre'] = $usuario_bd['nombre'];

// --- Redirigir al inicio en modo administrador ---
header('Location: /apps/side-arc/index.php');
exit;