Esta sección se ocupa de cómo configurar la gestión de sesiones y ajustarla a tus necesidades específicas. Esta documentación incluye los controladores de guardado, que almacenan y recuperan datos de la sesión y configuración del comportamiento de la sesión.
El flujo de trabajo en la sesión PHP tiene 6 posibles operaciones que pueden ocurrir. El flujo de sesión normal sigue el proceso de apertura, lectura, escritura y cierre, con la posibilidad de destrucción y gc (por garbage collection o recolección de basura, la cual cerrará todas las sesiones abiertas: la gc se invoca aleatoriamente de acuerdo a la configuración de PHP y si es llamada directamente, su invocación se difiere hasta después de una operación de apertura). Puedes leer más sobre esto en php.net/session.customhandler
Los llamados controladores ‘nativos’, son controladores de guardado que son o bien compilados en PHP o proporcionados por extensiones PHP, como PHP SQLite, PHP-Memcached, etc.
Todos los controladores de guardado nativos son internos a PHP y como tal, no tienen enfrente API pública. Ellos deben estar configurados en las directivas ini de PHP, por lo general session.save_path y potencialmente otros controladores específicos para la directiva. Puedes encontrar los detalles específicos en el bloque de documentación del método setOptions() de cada clase.
Mientras los controladores de guardado nativos se pueden activar utilizando directamente ini_set('session.save_handler', $nombre);, Symfony2 proporciona una manera conveniente de activar estos en la misma forma que los controladores personalizados.
Symfony2 proporciona controladores para el siguiente controlador de guardado nativo, por ejemplo:
- Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeFileSessionHandler;
Ejemplo de uso:
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeFileSessionHandler;
$storage = new NativeSessionStorage(array(), new NativeFileSessionHandler());
$session = new Session($storage);
Nota
Salvo el controlador files que está integrado en PHP y siempre disponible, la disponibilidad de los otros controladores depende de las extensiones de PHP activas en tiempo de ejecución.
Nota
Los controladores de guardado nativos proporcionan una rápida solución de almacenamiento de sesión, sin embargo, en sistemas complejos donde se necesita más control, los controladores de guardado personalizados pueden proporcionar más libertad y flexibilidad. Symfony2 proporciona varias implementaciones que se pueden personalizar aún más según sea necesario.
Los controladores personalizados son aquellos que sustituyen por completo a los controladores de guardado de sesión integrados en PHP, proveyendo seis funciones retrollamadas que PHP invoca internamente en varios puntos en el flujo de trabajo de la sesión.
HttpFoundation de Symfony2, por omisión, ofrece algunos de estos y fácilmente te pueden servir como ejemplos, si quieres escribir uno propio.
- Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler
- Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcacheSessionHandler
- Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcachedSessionHandler
- Symfony\Component\HttpFoundation\Session\Storage\Handler\MongoDbSessionHandler
- Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler
Ejemplo de uso:
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Session\Storage\SessionStorage;
use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler;
$storage = new NativeSessionStorage(array(), new PdoSessionHandler());
$session = new Session($storage);
La clase Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage puede ajustar la mayoría de las directivas de configuración de PHP, las cuales están documentadas en php.net/session.configuration.
Para configurar estas opciones, pasa las claves (omitiendo la primera parte session. de la clave) como un arreglo de clave/valor como el argumento $options del constructor. O ajústalas a través del método setOptions().
En aras de la claridad, algunas de las opciones principales se explican en esta documentación.
Para mayor seguridad, generalmente se recomienda enviar fragmentos de sesión como cookies de sesión. Puedes configurar el tiempo de vida de las cookies de sesión, especificando la duración (en segundos) usando la clave cookie_lifetime en el argumento $options del constructor en Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage.
Establecer una cookie_lifetime a 0 provocará que la cookie viva sólo mientras el navegador sigue abierto. En general, cookie_lifetime se establece en un número de días, semanas o meses relativamente grande. No es raro dejar cookies durante un año o más, dependiendo de la aplicación.
Dado que las cookies de sesión son sólo una muestra del lado del cliente, estas son menos importantes al controlar los detalles de la configuración de seguridad que en última instancia sólo se pueden controlar en el lado del servidor.
Nota
La opción cookie_lifetime es el número de segundos que la cookie debería vivir, esta no es una marca de tiempo Unix. La cookie de sesión resultante será sellada durante un plazo de time() + cookie_lifetime donde el tiempo se toma desde el servidor.
Cuando se abre una sesión, PHP llama aleatoriamente al controlador gc de acuerdo a la probabilidad establecida por session.gc_probability / session.gc_divisor. Por ejemplo, si éstos se establecieron en 5/100, respectivamente, significaría una probabilidad del 5%. Del mismo modo, 3/4 significaría invocarlo en 3 de cada 4 oportunidades, es decir, un 75%.
Si se invoca el controlador de recolección de basura, PHP pasará el valor almacenado en la directiva ini session.gc_maxlifetime de PHP. El significado en este contexto es que se debería suprimir cualquier sesión almacenada que se guardó por más de maxlifetime. Esto le permite a uno expirar los registros basándose en el tiempo de inactividad.
Puedes configurar estas opciones pasando gc_probability, gc_divisor y gc_maxlifetime en un arreglo al constructor de Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage o al método setOptions()().
Cuando se crea una nueva sesión, significa que Symfony2 emite una nueva cookie de sesión para el cliente, la cookie será sellada con un tiempo de caducidad. Este se calcula sumando el valor de configuración de session.cookie_lifetime en PHP con la hora actual del servidor.
Nota
PHP sólo emitirá una cookie una vez. Se espera que el cliente guarde esa cookie toda la vida. Sólo se otorgará una nueva cookie cuando la sesión sea destruida, se elimine la cookie en el navegador, o se vuelva a regenerar el identificador de sesión usando los métodos migrate() o invalidate() de la clase Session.
La duración inicial de la cookie se puede establecer configurando NativeSessionStorage utilizando el método setOptions(array('cookie_lifetime' => 1234)).
Nota
Una galeta con una vida útil de 0 significa que la galleta expira al cerrar el navegador.
A menudo hay circunstancias en las que posiblemente quieras proteger, o reducir al mínimo el uso no autorizado de una sesión cuando un usuario se aleja de su terminal mientras está conectado destruyendo la sesión después de cierto periodo de tiempo de inactividad. Por ejemplo, es común que las aplicaciones de banca cierren la sesión después de sólo 5 a 10 minutos de inactividad. Ajustar la duración de la cookie aquí no es apropiado debido a que el cliente la puede manipular, por lo que debemos hacer la expiración de lado del servidor. La forma más fácil es implementarla a través de la recolección de basura la cual se ejecuta con razonable frecuencia. El lifetime de la cookie se establece a un valor relativamente alto, y la recolección de basura maxlifetime se establecería para destruir sesiones en cualquiera que sea el periodo de inactividad deseado.
La otra opción es comprobar específicamente si una sesión ha caducado después de haber iniciado la sesión. La sesión se puede destruir si es necesario. Este método de procesamiento puede permitir la integración de la expiración de sesiones en la experiencia del usuario, por ejemplo, visualizando un mensaje.
Symfony2 registra algunos metadatos básicos acerca de cada sesión para darte completa libertad en este ámbito.
Las sesiones están decoradas con un poco de metadatos básicos para permitirte un control preciso sobre la configuración de seguridad. El objeto Sesión tiene un captador de metadatos, getMetadataBag() que expone una instancia de Symfony\Component\HttpFoundation\Session\Storage\MetadataBag:
$session->getMetadataBag()->getCreated();
$session->getMetadataBag()->getLastUsed();
Ambos métodos devuelven una marca de tiempo Unix (relativa al servidor).
Puedes utilizar estos metadatos para expirar la sesión explícitamente en el acceso, por ejemplo:
$session->start();
if (time() - $session->getMetadataBag()->getLastUsed() > $maxIdleTime) {
$session->invalidate();
throw new SessionExpired(); // redirige a la página de sesión expirada
}
También es posible decir cuál es el cookie_lifetime establecido en una cookie en particular leyendo el método getLifetime():
$session->getMetadataBag()->getLifetime();
Puedes determinar el tiempo de caducidad de la cookie sumando la fecha y hora de creación y el lifetime.
A partir de PHP 5.4.0, están disponibles SessionHandler y SessionHandlerInterface. Symfony 2.1 proporciona compatibilidad para SessionHandlerInterface por lo tanto la puedes utilizar en PHP 5.3. Esto, gratamente mejora la interoperabilidad con otras bibliotecas.
SessionHandler es una clase interna especial de PHP que expone los controladores de guardado nativos para el espacio de usuario de PHP.
Con el fin de proporcionar una solución para aquellos que utilizan PHP 5.4, Symfony2 tiene una clase especial llamada Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler que bajo PHP 5.4, se extiende desde SessionHandler y bajo PHP 5.3 es sólo una clase base vacía. Esto proporciona interesantes oportunidades para aprovechar la funcionalidad de PHP 5.4 si está disponible.
Hay dos tipos de controladores delegados de clases de guardado que heredan de Symfony\Component\HttpFoundation\Session\Storage\Handler\AbstractProxy: estas son Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeProxy y Symfony\Component\HttpFoundation\Session\Storage\Handler\SessionHandlerProxy.
La Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage automáticamente inyecta los controladores de guardado en un controlador de guardado delegado, a menos que ya lo envuelva uno.
La clase Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeProxy se utiliza automáticamente en PHP 5.3, cuando los controladores de guardado internos de PHP se especifican usando las clases Native*SessionHandler, mientras que la clase Symfony\Component\HttpFoundation\Session\Storage\Handler\SessionHandlerProxy se utiliza para envolver cualquier controlador de guardado personalizado, esta implementa la SessionHandlerInterface.
En PHP 5.4 y superior, todos los controladores de sesión implementan la SessionHandlerInterface incluyendo las clases Native*SessionHandler que heredan de SessionHandler.
El mecanismo delegado te permite involucrarte profundamente en las clases controladoras de guardado de sesión. Podrías utilizar un delegado, por ejemplo, para cifrar cualquier transacción de la sesión sin el conocimiento específico del controlador de guardado.