Esta guía te mostrará cómo guardar las sesiones de forma segura en una base de datos de mySQL. También aprenderás a cifrar todos los datos de la sesión que vayan a la base de datos, o sea que, si alguien logra hackear la base de datos, todos los datos de las sesiones estarán con un cifrado AES de 256 bits.

Método 1
Método 1 de 3:
Configurar la base de datos mySQL

  1. 1
    Crea una base de datos MySQL.
    En esta guía crearemos una base de datos llamada sesiones_seguras.
    Observa cómo se crea una base de datos en phpMyAdmin.
    O puedes usar el código SQL que hay a continuación para crear una.

    Crea el código de la base de datos:
    CREATE DATABASE `sesiones_seguras` ;
    

    Nota: Algunos servicios de alojamiento no permiten crear una base de datos con phpMyAdmin, aprende a hacerlo en cPanel.
  2. 2
    Crea un usuario que solo tenga privilegios para SELECT, INSERT y DELETE.
    O sea que si llegara a haber alguna brecha en la seguridad de nuestro script, el hacker no podrá eliminar tablas de la base de datos. Si estás realmente paranoico, crea un usuario distinto para cada función.

    • Usuario: "sec_user"
    • Contraseña: "eKcGZr59zAa2BEWU"


    Crea el código de usuario:
    CREATE USER 'sec_user'@'localhost' IDENTIFIED BY 'eKcGZr59zAa2BEWU';
    GRANT SELECT, INSERT, UPDATE, DELETE ON `sesiones_seguras`.* TO 'sec_user'@'localhost';
    

    Nota: una buena idea sería cambiar la contraseña del código de arriba al ejecutarlo en tu propio servidor (asegúrate de cambiar también el código PHP). Recuerda que no necesitas recordar la contraseña, así que la puedes hacer lo más difícil que puedas. Aquí hay un generador de contraseñas aleatorias.
  3. 3
    Crea una tabla MySQL llamada "sesiones".
    El código que hay a continuación creará una tabla con 4 campos (id, horario, data, clave_sesion).

    Crea la tabla "sesiones":
    CREATE TABLE `sesiones` (
      `id` char(128) NOT NULL,
      `horario` char(10) NOT NULL,
      `data` text NOT NULL,
      `clave_sesion` char(128) NOT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
    

    Usa el tipo de datos CHAR para los campos con longitud conocida, como los campos "id" y "clave_sesion" que siempre tendrán 128 caracteres de largo. Al usar CHAR ahorraremos potencia de procesamiento.

Método 2
Método 2 de 3:
Crear un archivo sesion.class.php

  1. 1
    Crea una clase.
    Para inicializar una clase nueva, necesitarás ingresar el código que sigue:

    Clase nueva:
    class session {
    
  2. 2
    Crea la función __construct.
    Se llamará a esta función cada vez que crees una instancia nueva de un objeto usando la clase 'sesion'. Puedes leer sobre la función PHP _construct aquí.
    Esta función configura nuestro manejador de sesión personalizado para que esté disponible ni bien se inicialice la clase (o sea, que se haga, se compile o se construya).

    __construct function:
    function __construct() {
       // configura las funciones de la sesión personalizada.
       session_set_save_handler(array($this, 'open'), array($this, 'close'), array($this, 'read'), array($this, 'write'), array($this, 'destroy'), array($this, 'gc'));
    
       // Esta línea evita efectos inesperados al usar objetos como manipuladores de guardado.
       register_shutdown_function('session_write_close');
    }
    
  3. 3
    Crea una función inicio_sesion.
    Se llamará a esta función cada vez que alguien quiera iniciar una sesión nueva, en lugar de usar session_start();. Observa los comentarios del código para ver lo que hace cada línea.

    función inicio_sesion:
    function inicio_sesion($session_name, $secure) {
       // Asegúrate de que la cookie de sesión no pueda accederse por javascript.
       $httponly = true;
    	
       // algoritmo hash para usar con sessionid. (usa hash_algos() para ver una lista de los hash disponibles)
       $session_hash = 'sha512';
    	
       // Revisa si hay un hash disponible
       if (in_array($session_hash, hash_algos())) {
          // Configura la función hash.
          ini_set('session.hash_function', $session_hash);
       }
       // Cuántos bits por caracter del hash.
       // Los valores posibles son '4' (0-9, a-f), '5' (0-9, a-v), y '6' (0-9, a-z, A-Z, "-", ",").
       ini_set('session.hash_bits_per_character', 5);
    	
       // Fuerza a la sesión para que sólo use cookies, no variables URL.
       ini_set('session.use_only_cookies', 1);
    	
       // Consigue los parámetros de la cookie de la sesión
       $cookieParams = session_get_cookie_params(); 
       // Configura los parámetros
       session_set_cookie_params($cookieParams["lifetime"], $cookieParams["path"], $cookieParams["domain"], $secure, $httponly); 
       // Cambia el nombre de la sesión
       session_name($session_name);
       // Ahora podemos iniciar la sesión
       session_start();
       // Esta línea regenera la sesión y elimina la anterior.
       // También genera una nueva clave de cifrado en la base de datos. 
       session_regenerate_id(true);	
    }
    
  4. 4
    Crea una función abrir.
    Las sesiones PHP llamarán a esta función al iniciar una sesión nueva, la usamos para iniciar una conexión nueva en la base de datos.

    función abrir:
    function abrir() {
       $host = 'localhost';
       $user = 'sec_user';
       $pass = 'eKcGZr59zAa2BEWU';
       $name = 'sesiones_seguras';
       $mysqli = new mysqli($host, $user, $pass, $name);
       $this->db = $mysqli;
       return true;
    }
    
  5. 5
    Crea una función cerrar.
    This function will be called when the sesiones want to be closed.

    función cerrar:
    function cerrar() {
       $this->db->cerrar();
       return true;
    }
    
  6. 6
    Crea una función leer.
    PHP llamará a esta función cuando intentes acceder a una sesión, por ejemplo cuando uses echo $_SESSION['algo'];. Como puede haber muchas llamadas a esta función en una sola página, aprovecha las declaraciones preparadas, no solo por seguridad sino también por rendimiento. Solo prepara la declaración una vez y luego ejecútala muchas veces.
    También descifra los datos de sesión cifrados en la base de datos. Usarás un cifrado AES de 256 bits en las sesiones.

    función leer:
    function leer($id) {
       if(!isset($this->read_stmt)) {
          $this->read_stmt = $this->db->prepare("SELECT data FROM sesiones WHERE id = ? LIMIT 1");
       }
       $this->read_stmt->bind_param('s', $id);
       $this->read_stmt->execute();
       $this->read_stmt->store_result();
       $this->read_stmt->bind_result($data);
       $this->read_stmt->fetch();
       $key = $this->getkey($id);
       $data = $this->decrypt($data, $key);
       return $data;
    }
    
  7. 7
    Crea una función escribir.
    Se usará esta función cuando asignes un valor a una sesión, por ejemplo $_SESSION['algo'] = 'otra cosa';. La función cifra todos los datos para insertarlos en la base de datos.

    función escribir:
    function escribir($id, $data) {
       // Consigue una clave única
       $key = $this->getkey($id);
       // Cifra los datos
       $data = $this->encrypt($data, $key);
       
       $time = time();
       if(!isset($this->w_stmt)) {
          $this->w_stmt = $this->db->prepare("REPLACE INTO sesiones (id, horario, data, clave_sesion) VALUES (?, ?, ?, ?)");
       }
       
       $this->w_stmt->bind_param('siss', $id, $time, $data, $key);
       $this->w_stmt->execute();
       return true;
    }
    
  8. 8
    Crea una función destruir.
    Esta función elimina la sesión de la base de datos, la usa PHP cuando llamas a funciones como session__destroy();.

    función destruir:
    function destruir($id) {
       if(!isset($this->delete_stmt)) {
          $this->delete_stmt = $this->db->prepare("DELETE FROM sesiones WHERE id = ?");
       }
       $this->delete_stmt->bind_param('s', $id);
       $this->delete_stmt->execute();
       return true;
    }
    
  9. 9
    Crea una función gc (recolector de basura, por sus siglas en inglés).
    Se llama a la función recolector de basura para eliminar las sesiones antiguas. La frecuencia con la que se llame a esta función estará determinada por las dos directivas de configuración, session.gc_probability y session.gc_divisor.

    función gc():
    function gc($max) {
       if(!isset($this->gc_stmt)) {
          $this->gc_stmt = $this->db->prepare("DELETE FROM sesiones WHERE horario < ?");
       }
       $old = time() - $max;
       $this->gc_stmt->bind_param('s', $old);
       $this->gc_stmt->execute();
       return true;
    }
    
  10. 10
    Crea una función getkey.
    Se usa esta función para obtener la clave única para cifrar la tabla de sesiones. Si no hay una sesión, simplemente devuelve una clave aleatoria nueva para cifrar.

    función getkey():
    private function getkey($id) {
       if(!isset($this->key_stmt)) {
          $this->key_stmt = $this->db->prepare("SELECT clave_sesion FROM sesiones WHERE id = ? LIMIT 1");
       }
       $this->key_stmt->bind_param('s', $id);
       $this->key_stmt->execute();
       $this->key_stmt->store_result();
       if($this->key_stmt->num_rows == 1) { 
          $this->key_stmt->bind_result($key);
          $this->key_stmt->fetch();
          return $key;
       } else {
          $random_key = hash('sha512', uniqid(mt_rand(1, mt_getrandmax()), true));
          return $random_key;
       }
    }
    
  11. 11
    Crea las funciones cifrado y descifrado.
    Estas funciones cifran los datos de las sesiones con una clave de cifrado de la base de datos que es distinta para cada sesión. No se usa directamente la clave de cifrado, pero la usarás para crear el hash de clave de forma más aleatoria aún.

    fuciones encrypt() y decrypt():
    private function encrypt($data, $key) {
       $salt = 'cH!swe!retReGu7W6bEDRup7usuDUh9THeD2CHeGE*ewr4n39=E@rAsp7c-Ph@pH';
       $key = substr(hash('sha256', $salt.$key.$salt), 0, 32);
       $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
       $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
       $encrypted = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $data, MCRYPT_MODE_ECB, $iv));
       return $encrypted;
    }
    private function decrypt($data, $key) {
       $salt = 'cH!swe!retReGu7W6bEDRup7usuDUh9THeD2CHeGE*ewr4n39=E@rAsp7c-Ph@pH';
       $key = substr(hash('sha256', $salt.$key.$salt), 0, 32);
       $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
       $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
       $decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, base64_decode($data), MCRYPT_MODE_ECB, $iv);
       return $decrypted;
    }
    
  12. 12
    Cierra las clases.
    Aquí simplemente cierra las clases con llaves:

    Cerrar las clases:
    }
    

Método 3
Método 3 de 3:
Crear páginas con sesiones

  1. 1
    Usa sesiones con el administrador de sesiones personalizado.
    A continuación se muestra cómo iniciar una sesión nueva; necesitarías incluir esto en todas las páginas que quieras acceder con las sesiones, úsala en vez de session_start();

    Inicia una sesión:
    require('sesion.class.php');
    $session = new session();
    // Ponlo en true si usas https
    $session->inicio_sesion('_s', false);
    
    $_SESSION['algo'] = 'Un valor.';
    echo $_SESSION['algo'];
    

Acerca de este wikiHow

wikiHow es un "wiki", lo que significa que muchos de nuestros artículos están escritos por varios autores. Para crear este artículo, 10 personas, algunas anónimas, han trabajado para editarlo y mejorarlo con el tiempo. Este artículo ha sido visto 22 318 veces.
Categorías: Programación