Sesiones

HTTP es un protocolo sin estado, pero casi todas las aplicaciones necesitan mantener un estado entre peticiones, por ejemplo, el contenido de un carrito de la compra. Para esto se utiliza una sesión. Veamos

  • cómo usar las sesiones
  • cómo evitar conflictos de nombres
  • cómo fijar la caducidad

Cuando se utilizan sesiones, cada usuario recibe un identificador único llamado ID de sesión, que se pasa en una cookie. Esto sirve como clave para los datos de sesión. A diferencia de las cookies, que se almacenan en el navegador, los datos de sesión se almacenan en el servidor.

Configuramos la sesión en la configuración, la elección del tiempo de expiración es importante.

La sesión es gestionada por el objeto Nette\Http\Session, que se obtiene pasándolo mediante inyección de dependencia. En presentadores simplemente llame a $session = $this->getSession().

Instalación y requisitos

Inicio de la sesión

Por defecto, Nette iniciará una sesión automáticamente en el momento en que empecemos a leer de ella o a escribir datos en ella. Para iniciar una sesión manualmente, utilice $session->start().

PHP envía cabeceras HTTP que afectan a la caché cuando se inicia la sesión, ver session_cache_limiter, y posiblemente una cookie con el ID de sesión. Por lo tanto, siempre es necesario iniciar la sesión antes de enviar cualquier salida al navegador, de lo contrario se lanzará una excepción. Por lo tanto, si sabe que se va a utilizar una sesión durante la representación de la página, iníciela manualmente antes, por ejemplo en el presentador.

En modo desarrollador, Tracy inicia la sesión porque la utiliza para mostrar barras de redirección y peticiones AJAX en la Tracy Bar.

Sección

En PHP puro, el almacén de datos de sesión se implementa como un array accesible a través de una variable global $_SESSION. El problema es que las aplicaciones normalmente consisten en un número de partes independientes, y si todas tienen un mismo array disponible, tarde o temprano ocurrirá una colisión de nombres.

Nette Framework resuelve el problema dividiendo todo el espacio en secciones (objetos Nette\Http\SessionSection). Cada unidad utiliza entonces su propia sección con un nombre único y no pueden producirse colisiones.

Obtenemos la sección del gestor de sesiones:

$section = $session->getSection('unique name');

En el presentador basta con llamar a getSession() con el parámetro:

// $this es Presentador
$section = $this->getSession('unique name');

La existencia de la sección puede comprobarse mediante el método $session->hasSection('unique name').

La sección en sí es muy fácil de trabajar con los métodos set(), get() y remove():

// escritura de variables
$section->set('nombreusuario', 'franta');

// lectura de una variable, devuelve null si no existe
echo $section->get('nombredeusuario');

// eliminar variable
$section->remove('userName');

Es posible utilizar el ciclo foreach para obtener todas las variables de la sección:

foreach ($section as $key => $val) {
	echo "$key = $val";
}

Cómo fijar la caducidad

La caducidad puede establecerse para secciones individuales o incluso variables individuales. Podemos dejar que el login del usuario caduque en 20 minutos, pero seguir recordando el contenido de un carrito de la compra.

// la sección caducará a los 20 minutos
$section->setExpiration('20 minutes');

El tercer parámetro del método set() se utiliza para establecer la caducidad de variables individuales:

// la variable 'flash' caduca a los 30 segundos
$section->set('flash', $message, '30 seconds');

Recuerda que el tiempo de expiración de toda la sesión (ver configuración de la sesión) debe ser igual o superior al tiempo establecido para secciones o variables individuales.

La anulación de la caducidad previamente fijada puede conseguirse mediante el método removeExpiration(). La eliminación inmediata de toda la sección se asegurará mediante el método remove().

Eventos $onStart, $onBeforeWrite

El objeto Nette\Http\Session tiene los eventos $onStart y $onBeforeWrite, por lo que puedes añadir callbacks que sean llamados después de que la sesión se inicie o antes de que se escriba en disco y luego se termine.

$session->onBeforeWrite[] = function () {
	// escribir datos en la sesión
	$this->section->set('basket', $this->basket);
};

Gestión de sesiones

Visión general de los métodos de la clase Nette\Http\Session para la gestión de sesiones:

start(): void

Inicia una sesión.

isStarted(): bool

¿Se ha iniciado la sesión?

close(): void

Finaliza la sesión. La sesión termina automáticamente al final del script.

destroy(): void

Finaliza y borra la sesión.

exists(): bool

¿Contiene la petición HTTP una cookie con un ID de sesión?

regenerateId(): void

Genera un nuevo ID de sesión aleatorio. Los datos permanecen inalterados.

getId(): string

Devuelve el ID de sesión.

Configuración

Configuramos la sesión en configuración. Si está escribiendo una aplicación que no utiliza un contenedor DI, utilice estos métodos para configurarla. Deben ser llamados antes de iniciar la sesión.

setName(string $name): static

Establece el nombre de la cookie que se utiliza para transmitir el ID de sesión. El nombre por defecto es PHPSESSID. Esto es útil si ejecuta varias aplicaciones diferentes en el mismo sitio.

getName(): string

Devuelve el nombre de la cookie de sesión.

setOptions(array $options)static

Configura la sesión. Es posible establecer todas las directivas de sesión de PHP (en formato camelCase, por ejemplo, escribir savePath en lugar de session.save_path) y también readAndClose.

setExpiration(?string $time)static

Establece el tiempo de inactividad tras el cual expira la sesión.

setCookieParameters(string $path, string $domain=null, bool $secure=null, string $samesite=null)static

Establece los parámetros para las cookies. Puede cambiar los valores predeterminados de los parámetros en configuration.

setSavePath(string $path)static

Establece el directorio donde se almacenan los archivos de sesión.

setHandler(\SessionHandlerInterface $handler)static

Establece el manejador personalizado, vea la documentación de PHP.

Seguridad

El servidor asume que se comunica con el mismo usuario mientras las peticiones contengan el mismo identificador de sesión. La tarea de los mecanismos de seguridad es garantizar que este comportamiento funciona realmente y que no hay posibilidad de sustituir o robar un identificador.

Por eso Nette Framework configura adecuadamente las directivas PHP para transferir el identificador de sesión sólo en las cookies, evitar el acceso desde JavaScript e ignorar los identificadores en la URL. Además en momentos críticos, como el login del usuario, genera un nuevo identificador de sesión.

La función ini_set se utiliza para configurar PHP, pero desafortunadamente, su uso está prohibido en algunos servicios de alojamiento web. Si es tu caso, intenta pedir a tu proveedor de hosting que te permita esta función, o al menos que configure su servidor adecuadamente.

versión: 4.0