7. Formularios

Forms y procesamiento de envíos

Otra de las características más potentes de PHP es la forma de gestionar formularios HTML. El concepto básico que es importante entender es que cualquier elemento de un formulario estará disponible automáticamente en sus scripts de PHP.

Al diseñar un formulario debemos indicar la página PHP que procesará el formulario, así como el método por el que se le pasará la información a la página.

<form action="accion.php" method="post">
    <p>Su nombre: <input type="text" name="name" /></p>
    <p>Su edad: <input type="text" name="edad" /></p>
    <p><input type="submit" /></p>
</form>

Al presionar el botón “Enviar”, el contenido del cuadro de texto se envía a la página que indicamos en el atributo ACCIÓN de la etiqueta FORM.

PHP tiene una serie de variables predefinidas de tal forma que cuando la página PHP recibe los datos del formulario automáticamente crea una variable para cada elemento del FORMULARIO, esta variable creada tiene el mismo nombre que el cuadro de texto de la página anterior y el valor que ingresamos. En este ejemplo, se creó una variable llamada $name con el valor ingresado por el navegador.

Estas variables están dispoñibles nas matrices PHP predefinidas. Polo tanto teremos que usar $_GET[‘variable’] para acceder ó contido da variable que nos chega polo método GET, ou ben $_POST[‘variable’] si estamos accedendo a unha variable que nos chega polo método POST.

procesa.php

Métodos GET y POST

A diferenza entre estes dous métodos radica na forma de enviar os datos á páxina, mentres que o método GET envía os datos usando a URL, o método POST envíaos pola entrada estándar STDIO.

El resultado final es el mismo, solo que con el método GET podemos ver los parámetros pasados ​​tal como están codificados en la URL.

MÉTODO CONCEPTO OBSERVACIONES
GET GET lleva los datos de forma “visible” al cliente (navegador web). El medio de envío es la URL. Los datos los puede ver cualquiera. Los datos son visibles por la URL, por ejemplo: www.aprenderaprogramar.com/action.php?nombre=pedro&apellidos1= gomez
POST POST consiste en datos “ocultos” (porque el cliente no los ve) enviados por un formulario cuyo método de envío es post. Es adecuado para formularios. Los datos no son visibles. La ventaja de usar POST es que estos datos no son visibles al usuario de la web. En el caso de usar get, el propio usuario podría modificar la URL escribiendo diferentes parámetros a los reales en su navegador, dando lugar a que la información tratada no sea la prevista.

Es recomendable elegir GET para aquellas solicitudes en las que se soliciten pocos datos y POST para aquellas en las que sea necesario enviar información que pueda superar los 512 bytes en total, ya que el método GET no podría recibir todos los datos. También es recomendable utilizar el método POST para enviar datos con mayor seguridad (contraseñas, códigos especiales, etc.) ya que en el método GET podrían verse en la URL del navegador.

Otros aspectos

  • Tener precaución con vulnerabilidades típicas como la inyección de código. htmlspecialchars() garantiza que cualquier carácter que sea especial en html se codifique adecuadamente, de manera que nadie pueda inyectar etiquetas HTML o Javascript en la página.

  • En PHP, también puedes tratar con entradas de XForms; aunque probablemente al principio te sientas cómodo con los formularios de HTML, los cuales están ampliamente respaldados.

7.1. Validación de formularios

Con la validación de formularios podemos procesar formularios PHP teniendo en cuenta la seguridad. La validación adecuada de los datos del formulario es importante para proteger su formulario de ataques.

Imaginemos que tenemos el siguiente html:

<h2>PHP Ejemplo de validación de Formularios</h2>
<form method="post" action="procesar.php">>  
  Nombre: <input type="text" name="name">
  <br><br>
  E-mail: <input type="text" name="email">
  <br><br>
  Website: <input type="text" name="website">
  <br><br>
  Comentario: <textarea name="comment" rows="5" cols="40"></textarea>
  <br><br>
  Género:
  <input type="radio" name="gender" value="female">Mujer
  <input type="radio" name="gender" value="male">Hombre
  <input type="radio" name="gender" value="other">Other
  <br><br>
  <input type="submit" name="submit" value="Submit">  
</form>

Como podemos observar cuando enviamos el formulario lo enviamos por el método POST.

## Procesar en la misma página

Si quisiéramos enviar la información a la misma página donde tenemos nuestro formulario podemos utilizar la función $_SERVER["PHP_SELF"].

<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">

Entonces, $_SERVER[“PHP_SELF”] envía los datos del formulario enviado a la página misma, en lugar de saltar a una página diferente. De esta forma, el usuario recibirá mensajes de error en la misma página que el formulario.

htmlspecialchars

La función htmlspecialchars() convierte los caracteres especiales en entidades HTML. Esto significa que reemplazará caracteres HTML como < y > con < y >. Esto evita que los atacantes exploten el código inyectando código HTML o Javascript (ataques de secuencias de comandos entre sitios) en los formularios.

Seguridad en los formularios PHP

Si se usa PHP_SELF en su página, un usuario puede ingresar una barra inclinada (/) y luego algunos comandos de Cross Site Scripting (XSS) que se ejecutarían en su página.

Cross Site Scripting (XSS)

Cross-site scripting (XSS) es un tipo de vulnerabilidad de seguridad informática que normalmente se encuentra en las aplicaciones web. XSS permite a los atacantes inyectar secuencias de comandos del lado del cliente en las páginas web vistas por otros usuarios.

Supongamos que tenemos el siguiente formulario en una página llamada “test_form.php”:

<form method="post" action="<?php echo $_SERVER["PHP_SELF"];?>">

Ahora, si un usuario ingresa la URL normal en la barra de direcciones como “http://www.example.com/test_form.php", el código anterior se traducirá a:

<form method="post" action="test_form.php">

Hasta aquí todo bien.

Sin embargo, considere que un usuario ingresa la siguiente URL en la barra de direcciones:

http://www.example.com/test_form.php/%22%3E%3Cscript%3Ealert('hacked')%3C/script%3E

En este caso, el código anterior se traducirá a:

<form method="post" action="test_form.php/"><script>alert('hacked')</script>

Este código agrega una etiqueta de secuencia de comandos y un comando de alerta. Y cuando se cargue la página, se ejecutará el código JavaScript (el usuario verá un cuadro de alerta). Este es solo un ejemplo simple e inofensivo de cómo se puede explotar la variable PHP_SELF.

Tenga en cuenta que se puede agregar cualquier código JavaScript dentro de la etiqueta <script>. Un pirata informático puede redirigir al usuario a un archivo en otro servidor, y ese archivo puede contener un código malicioso que puede alterar las variables globales o enviar el formulario a otra dirección para guardar los datos del usuario, por ejemplo.

¿Cómo evitar los exploits de $_SERVER[“PHP_SELF”]?

Las vulnerabilidades de $_SERVER["PHP_SELF"] pueden evitarse utilizando la función htmlspecialchars().

El código del formulario debería verse así:

<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">

La función htmlspecialchars() convierte los caracteres especiales en entidades HTML. Ahora, si el usuario intenta explotar la variable PHP_SELF, dará como resultado el siguiente resultado:

<form method="post" action="test_form.php/&quot;&gt;&lt;script&gt;alert('hacked')&lt;/script&gt;">

¡El intento de explotación falla y no se produce ningún daño!

Validar datos de Formularios en PHP

Lo primero que haremos será pasar todas las variables a través de la función htmlspecialchars() de PHP. También haremos dos cosas más cuando el usuario envíe el formulario:

  1. Eliminar los caracteres innecesarios (espacio adicional, tabulación, nueva línea) de los datos de entrada del usuario (con la función PHP trim()).
  2. Eliminar las barras invertidas \ de los datos de entrada del usuario (con la función PHP stripslashes())
  3. El siguiente paso es crear una función que haga todas las comprobaciones por nosotros (lo cual es mucho más conveniente que escribir el mismo código una y otra vez).

Nombraremos la función test_input().

Funciones

Para comprender lo que es una función acude al punto 7.funciones.

Ahora, podemos verificar cada variable $_POST con la función test_input(), y el script se ve así:

<?php
// define variables and set to empty values
$name = $email = $gender = $comment = $website = "";

if ($_SERVER["REQUEST_METHOD"] == "POST") {
  $name = test_input($_POST["nombre"]);
  $email = test_input($_POST["email"]);
  $website = test_input($_POST["website"]);
  $comment = test_input($_POST["comentario"]);
  $gender = test_input($_POST["genero"]);
}

function test_input($data) {
  $data = trim($data);
  $data = stripslashes($data);
  $data = htmlspecialchars($data);
  return $data;
}
?>

7.2. Campos requeridos

Ahora veremos como hacer que los campos de entrada sean obligatorios y crear mensajes de error si es necesario.

Partiendo del código anterior, vamos a agregar unas sentencia if-else para cada variable $_POST. Esto verifica si la variable $_POST está vacía (con la función empty() de PHP). Si está vacía, se almacena un mensaje de error en las diferentes variables de error, y si no está vacío, envía los datos de entrada del usuario a través de la función test_input():

<?php
// define las variables y las inicializa a vacia
$nombreErr = $emailErr = $generoErr = $websiteErr = "";
$nombre = $email = $genero = $comentairo = $website = "";

if ($_SERVER["REQUEST_METHOD"] == "POST") {
  if (empty($_POST["nombre"])) {
    $nombreErr = "Nombre is required";
  } else {
    $nombre = test_input($_POST["nombre"]);
  }

  if (empty($_POST["email"])) {
    $emailErr = "Email is required";
  } else {
    $email = test_input($_POST["email"]);
  }

  if (empty($_POST["website"])) {
    $website = "";
  } else {
    $website = test_input($_POST["website"]);
  }

  if (empty($_POST["comentairo"])) {
    $comentairo = "";
  } else {
    $comentairo = test_input($_POST["comentairo"]);
  }

  if (empty($_POST["genero"])) {
    $generoErr = "genero is required";
  } else {
    $genero = test_input($_POST["genero"]);
  }
}
?>