He creado una clase en PHP para comprobar que los pares de clave y valor de un GET a los que enlazamos en un una página no han sido modificados por el usuario en la barra de direcciones del navegador en la página de destino.
Puede ser útil, por ejemplo, cuando queremos dar listas con soluciones a ejercicios a medida que avanza un curso. Con unos pares solucion / tema para que si una combinacion de número de solucion y tema no esta en lista de la pagina in¡cial no pueda ser visto por el usuario utilizando la barra de direcciones. También se puede cambiar la clave para cada usuario para identificar los que intentan saltarse la proteccion o para generar links que sólo puedan ser vistos por este usuario.
La forma en que lo hace es convirtiendo con
serialize en una cadena un array con los datos que irán en el GET añadiendo un elemento más con una palabra secreta. Con la cadena resultante generamos un hash MD5 que añadiremos al GET final. En la página siguiente hacemos el mismo proceso para comprobar que el GET que nos ha llegado genera la misma clave MD5.
seguridadpareshash.php
Código PHP:
<?php
/**
* Seguridad GET con un hash MD5
*
* Comprueba en el script de destino que los datos de un query al que
* enlaza nuestra pagina son los originales
*
* Puede ser útil, por ejemplo, cuando queremos dar listas con
* soluciones a ejercicios a medida que avanza un curso. Con unos pares
* solucion / tema para que si una combinacion de número de solucion
* y tema no esta en lista de la pagina no pueda ser visto por el
* usuario utilizando la barra de direcciones. También se puede cambiar
* la clave para cada usuario para identificar los que intentan
* saltarse la proteccion.
*
* Funciones de generacion:
* GeneraGETconHash -- Devuelve ?un=valor&otro=dato&sp=hash
* GeneraURL -- Devuelve unapagina.php?un=valor&otro=dato&sp=hash
* GeneraEnlace -- Devuelve <a href="unapagina.php?un=valor&otro=dato&sp=hash">Texto</a>
*
* Funcion de comprobacion:
* CompruebaGETconHash
*
*/
class CompruebaGetEntrePaginas
{
private $palabraSecreta;
function __construct()
{
$this->palabraSecreta = $this->GeneraPalabraSecreta ();
}
// Genera un GET con un codigo de comprobacion al final
public function GeneraGETconHash ($ArrayVariables)
{
$GETconHash = "";
$Liga = "";
foreach ($ArrayVariables as $UnaLlave => $UnValor){
$GETconHash .= $Liga.$UnaLlave."=".$UnValor;
$Liga = "&";
}
$GETconHash = "?".$GETconHash;
$ArrayVariables["palabraSecreta"] = $this->palabraSecreta;
$ClaveHash = hash ("md5",serialize($ArrayVariables));
$GETconHash .= $Liga."ps=".$ClaveHash;
return $GETconHash;
}
// Genera una URL completa, simplemente sirve para que haya menos
// funciones en la creación de la lista
public function GeneraURL ($ElArrayVariables,$NombreScript = "")
{
$elGETconHash = $this->GeneraGETconHash ($ElArrayVariables);
$PrefijoURL = (empty($NombreScript))? $_SERVER["PHP_SELF"] : $NombreScript;
$URLcompleta = $PrefijoURL.$elGETconHash;
return $URLcompleta;
}
// Genera un enlace completo
public function GeneraEnlace ($ElArrayVariables,$TextoEnlace,$NombreScript = ""){
$laURL = $this->GeneraURL($ElArrayVariables,$NombreScript);
return '<a href="'.$laURL.'">'.$TextoEnlace.'</a>';
}
// Comprueba que no se ha modificado la URL
public function CompruebaGETconHash ()
{
$ArrayTrabajo = $_GET;
$ValorHash = array_pop ($ArrayTrabajo);
$ArrayTrabajo["palabraSecreta"] = $this->palabraSecreta;
$ValorEsperadoHash = hash ("md5",serialize($ArrayTrabajo));
$comparacionValores = ($ValorHash === $ValorEsperadoHash)? TRUE : FALSE;
return $comparacionValores;
}
// Para mas seguridad se deberia reescribir esta funcion para leer el valor de una base de datos
private function GeneraPalabraSecreta ()
{
// Este valor de retorno debe cambiarse para mas seguridad
return 'flghusf';
}
}
?>
lista.php
Código PHP:
<?php
include_once ("seguridadpareshash.php");
// Iniciamos la clase de creacion/comprobacion
$CreaCompruebaURL = new CompruebaGetEntrePaginas ();
// En esta variable ponemos el nombre del script PHP. Si esta vacio
// o no esta definido se usa $_SERVER["PHP_SELF"]
$NombreScriptDestino = "resultadosprueba.php";
// Datos que iran en el GET y en el texto del enlace
$DatosGet = Array("solucion" => "12","tema" => "25");
$TextoEnlace = "Resultados al ejercicio 12 del tema 25";
// Mostramos el resultado en pantalla
print ($CreaCompruebaURL->GeneraEnlace ($DatosGet,$TextoEnlace,$NombreScriptDestino));
?>
resultadosprueba.php
Código PHP:
<?php
include_once ("seguridadpareshash.php");
$CreaCompruebaURL = new CompruebaGetEntrePaginas ();
// Comprobamos que coincide elcontenido de las variables de GET con el hash MD5 final
if ($CreaCompruebaURL->CompruebaGETconHash ()){
echo "Datos URL originales";
} else {
echo "Datos URL modificados";
}
?>