Apuntes php

PHP: Porque a veces necesitas un poco de caos en tu vida.

Validación y Sanitización de Datos en PHP

Vamos a ver como procesar entradas de usuarios (por ejemplo, de formularios HTML) para garantizar que sean seguras y válidas. Cubriremos funciones como filter_input(), filter_var(), técnicas de sanitización (htmlspecialchars(), strip_tags()), y el uso de expresiones regulares para validación.

¿Qué son Validación y Sanitización?

  • Validación: Verifica que los datos cumplen reglas específicas (por ejemplo, un correo válido o un número positivo).
  • Sanitización: Limpia los datos para eliminar contenido peligroso.

Valida primero, luego sanitiza si es necesario. Nunca confíes en datos de usuarios sin procesarlos.

filter_input() y filter_var()

PHP ofrece funciones específicas para validar datos de entrada de forma segura:

  • filter_input(tipo, nombre, filtro, opciones): Extrae y valida directamente una variable externa (por ejemplo, desde $_GET, $_POST, etc.).
  • filter_var(variable, filtro, opciones): Aplica un filtro a una variable ya obtenida.

PHP incluye una serie de filtros predefinidos para validar o sanear datos. Estos filtros se identifican mediante constantes como FILTER_VALIDATE_EMAIL o FILTER_VALIDATE_INT.

  • FILTER_VALIDATE_EMAIL: Comprueba si el valor es un correo válido.
  • FILTER_VALIDATE_INT: Comprueba si es un número entero válido (se puede limitar con un rango).
  • FILTER_SANITIZE_*: Existen también filtros para limpiar entradas (por ejemplo, eliminar etiquetas HTML o caracteres no válidos).

Estos filtros están disponibles como constantes definidas por PHP en el núcleo (no hay que importarlas ni definirlas). Puedes ver la lista completa en la documentación oficial: php.net.

Ejemplo: Validar un correo electrónico enviado por POST

<?php
declare(strict_types=1);

// Obtiene y valida un correo desde $_POST["email"]
$email = filter_input(INPUT_POST, "email", FILTER_VALIDATE_EMAIL) ?? "";

if ($email !== "") {
    echo "Correo válido: <b>$email</b>";
} else {
    echo "Correo inválido";
}
?>

Ejemplo: Validar un número entero entre 18 y 120

<?php
declare(strict_types=1);

// Valida que "edad" sea un número entero dentro del rango permitido
$edad = filter_input(INPUT_POST, "edad", FILTER_VALIDATE_INT, [
    "options" => ["min_range" => 18, "max_range" => 120]
]) ?? 0;

if ($edad !== 0) {
    echo "Edad válida: <b>$edad</b>";
} else {
    echo "Edad inválida";
}
?>

También puedes usar filter_var() si ya tienes la variable en una forma tradicional, como $email = $_POST["email"];

<?php
$email = $_POST["email"] ?? "";
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
    echo "Correo válido";
} else {
    echo "Correo inválido";
}
?>

Sanear datos con FILTER_SANITIZE_*

Además de validar, PHP permite sanear (limpiar) entradas eliminando caracteres no válidos o peligrosos. Esto se hace con filtros como:

  • FILTER_SANITIZE_EMAIL: Elimina caracteres no permitidos en correos.
  • FILTER_SANITIZE_STRING: Elimina etiquetas HTML y caracteres especiales (obsoleto, mejor htmlspecialchars, strip_tags o expresiones regulares
  • FILTER_SANITIZE_NUMBER_INT: Deja solo dígitos y signos +/-.
<?php
// Elimina caracteres inválidos de un correo
$email = filter_input(INPUT_POST, "email", FILTER_SANITIZE_EMAIL);

// Limpia una cadena eliminando etiquetas
$comentario = filter_var($_POST["comentario"] ?? "", FILTER_SANITIZE_STRING);
?>

Sanitización con htmlspecialchars() y strip_tags()

  • htmlspecialchars(): Convierte caracteres especiales en entidades HTML para prevenir XSS.
  • strip_tags(): Elimina etiquetas HTML y PHP.

Ejemplo: Sanitizar un comentario:

<?php
declare(strict_types=1);

$comentario = filter_input(INPUT_POST, "comentario", FILTER_SANITIZE_STRING) ?? "";
$comentario = htmlspecialchars($comentario, ENT_QUOTES, "UTF-8");
// Coincide: Texto limpio (por ejemplo, "<script>" se convierte en "&lt;script&gt;").
// No coincide: Código ejecutable o etiquetas HTML.
echo "Comentario seguro: <b>$comentario</b>\n";
?>

Ejemplo: Eliminar etiquetas:

<?php
declare(strict_types=1);

$texto = filter_input(INPUT_POST, "texto", FILTER_SANITIZE_STRING) ?? "";
$texto = strip_tags($texto);
// Coincide: Texto sin etiquetas HTML (por ejemplo, "<p>Hola</p>" se convierte en "Hola").
// No coincide: Texto con etiquetas HTML intactas.
echo "Texto limpio: <b>$texto</b>\n";
?>

Validación con Expresiones Regulares

Las regex son útiles para validar formatos específicos. Usa el Manual de Expresiones Regulares para más detalles.

Ejemplo: Validar un nombre:

<?php
declare(strict_types=1);

$nombre = filter_input(INPUT_POST, "nombre", FILTER_SANITIZE_STRING) ?? "";
$patron = "/^[A-Za-z\s]{2,50}$/";
// Coincide: Nombres con letras y espacios, 2-50 caracteres (por ejemplo, "Ana García").
// No coincide: "A1", "", "Ana@García".
preg_match($patron, $nombre);
?>

Formulario Seguro

Combina validación y sanitización en un formulario:

<?php
declare(strict_types=1);

$nombre = filter_input(INPUT_POST, "nombre", FILTER_SANITIZE_STRING) ?? "";
$email = filter_input(INPUT_POST, "email", FILTER_VALIDATE_EMAIL) ?? "";
$edad = filter_input(INPUT_POST, "edad", FILTER_VALIDATE_INT, [
    "options" => ["min_range" => 18, "max_range" => 120]
]) ?? 0;

$patron_nombre = "/^[A-Za-z\s]{2,50}$/";
// Coincide: Nombres válidos.
// No coincide: Nombres con números o caracteres especiales.
if (preg_match($patron_nombre, $nombre) && $email !== "" && $edad !== 0) {
    $nombre = htmlspecialchars($nombre, ENT_QUOTES, "UTF-8");
    echo "Datos válidos: <b>$nombre</b>, <b>$email</b>, <b>$edad</b>\n";
} else {
    echo "Datos inválidos\n";
}
?>

Seguridad adicional

  • Límite de longitud: Restringe el tamaño de las entradas:
<?php
if (strlen($nombre) > 50) {
    exit("Nombre demasiado largo");
}
?>
  • Evita inyecciones: Nunca uses datos sin validar en consultas SQL o patrones regex:
<?php
$patron = "/" . preg_quote($nombre, "/") . "/";
// Coincide: Nombre sanitizado como literal.
// No coincide: Entradas maliciosas.
?>
  • Usa filtros estrictos: Prefiere FILTER_VALIDATE_* sobre FILTER_SANITIZE_* para validación.
TOP