Files
LMS-Estafeta/admin/auth_guard.php
T

58 lines
2.3 KiB
PHP
Raw Normal View History

<?php
// Guard de autenticación + CSRF para endpoints de admin.
// Include al inicio de cada endpoint (require_once __DIR__.'/auth_guard.php';)
// Los endpoints de admin SIEMPRE responden JSON: nunca emitir HTML de avisos/errores.
@ini_set('display_errors', '0');
@ini_set('display_startup_errors', '0');
error_reporting(E_ALL & ~E_DEPRECATED & ~E_NOTICE);
// Descartar cualquier salida previa (BOM, espacios, avisos) antes del JSON.
if (ob_get_level() === 0) { @ob_start(); }
require_once dirname(__DIR__) . '/config.php';
if (session_status() === PHP_SESSION_NONE) {
session_name($CFG->sessionname);
session_start();
}
if (empty($_SESSION['usersession']) || empty($_SESSION['isadmin'])) {
while (ob_get_level() > 0) { @ob_end_clean(); }
http_response_code(403);
header('Content-Type: application/json; charset=utf-8');
echo json_encode(array('code' => '403', 'msg' => 'No autorizado'), JSON_UNESCAPED_UNICODE);
exit;
}
// Cualquier salida accidental (avisos/notices) antes del JSON se descarta aquí.
while (ob_get_level() > 0) { @ob_end_clean(); }
ob_start();
// Excepciones no controladas (p. ej. mysqli_sql_exception en PHP 8+) deben
// responder JSON, nunca HTML con stack trace (evita el "Unexpected token '<'").
set_exception_handler(function ($e) {
while (ob_get_level() > 0) { @ob_end_clean(); }
error_log('admin endpoint: ' . $e->getMessage());
http_response_code(500);
header('Content-Type: application/json; charset=utf-8');
echo json_encode(array('code' => '500', 'msg' => 'Error interno del servidor', 'error' => $e->getMessage()), JSON_UNESCAPED_UNICODE);
});
if (empty($_SESSION['csrf'])) {
$_SESSION['csrf'] = bin2hex(random_bytes(32));
}
// Verificación CSRF en métodos que cambian estado
$metodo = isset($_SERVER['REQUEST_METHOD']) ? strtoupper($_SERVER['REQUEST_METHOD']) : 'GET';
if ($metodo === 'POST' || $metodo === 'PUT' || $metodo === 'DELETE') {
$token = isset($_SERVER['HTTP_X_CSRF_TOKEN']) ? $_SERVER['HTTP_X_CSRF_TOKEN'] : '';
if ($token === '' && isset($_POST['csrf'])) { $token = $_POST['csrf']; }
if (!is_string($token) || !hash_equals($_SESSION['csrf'], $token)) {
http_response_code(403);
header('Content-Type: application/json; charset=utf-8');
echo json_encode(array('code' => '403', 'msg' => 'Token CSRF inválido'), JSON_UNESCAPED_UNICODE);
exit;
}
}