rss
twitter
  •  

Sesiones tradicionales en Codeigniter

| Posted in General |

23

Como muchos ya saben, el tradicional superglobal $_SESSION no está disponible en CodeIgniter y peor aun, las sesiones ni siquiera se almacenan del lado del servidor… son sólo vulgares cookies ! (lo que pone en riesgo la sensibilidad de los datos e incompatibilidad con ciertos navegadores).

Es tan tiránica esta filosofía que cuando mucho se te permite almacenarlas en una base de datos (algo absurdo para un proyecto pequeño).

En supuesto favor a la seguridad, resultó convertirse en su talón de Aquiles (son cientos de programadores como yo que han mostrado su disgusto por esta absurda forma de manejar los datos). Lo que justificó el nacimiento de Kohana.

En fin… como la comunidad es abierta y siempre hay gente inteligente en todos lados, no tardó alguien en crear una librería que remplaza al 100% la librería estándar Session.php que maneja por defecto las sesiones en CodeIgniter permitiéndonos usar los mismos métodos descritos en el manual oficial … pero comportándose como se supone debería comportarse.

Sólo necesitamos cargar la librería como acostumbramos hacer:

$this->load->library('session');

Y colocar nuestro archivo Session.php en nuestro application/libraries/


<?php  if (!defined('BASEPATH')) exit('No direct script access allowed');

/**
* Session class using native PHP session features and hardened against session fixation.
*
* @package     CodeIgniter
* @subpackage  Libraries
* @category    Sessions
* @author      Dariusz Debowczyk
* @link        http://www.codeigniter.com/user_guide/libraries/sessions.html
*/
class CI_Session {

	var $flash_key = 'flash'; // prefix for "flash" variables (eg. flash:new:message)

	function CI_Session()
	{
		$this->object =& get_instance();
		log_message('debug', "Native_session Class Initialized");
		$this->_sess_run();
	}

	/**
    * Regenerates session id
    */
	function regenerate_id()
	{
		// copy old session data, including its id
		$old_session_id = session_id();
		$old_session_data = $_SESSION;

		// regenerate session id and store it
		session_regenerate_id();
		$new_session_id = session_id();

		// switch to the old session and destroy its storage
		session_id($old_session_id);
		session_destroy();

		// switch back to the new session id and send the cookie
		session_id($new_session_id);
		session_start();

		// restore the old session data into the new session
		$_SESSION = $old_session_data;

		// update the session creation time
		$_SESSION['regenerated'] = time();

		// session_write_close() patch based on this thread
		// http://www.codeigniter.com/forums/viewthread/1624/
		// there is a question mark ?? as to side affects

		// end the current session and store session data.
		session_write_close();
	}

	/**
    * Destroys the session and erases session storage
    */
	function destroy()
	{
		unset($_SESSION);
		if ( isset( $_COOKIE[session_name()] ) )
		{
			setcookie(session_name(), '', time()-42000, '/');
		}
		session_destroy();
	}

	/**
    * Reads given session attribute value
    */
	function userdata($item)
	{
		if($item == 'session_id'){ //added for backward-compatibility
			return session_id();
		}else{
			return ( ! isset($_SESSION[$item])) ? false : $_SESSION[$item];
		}
	}

	/**
    * Sets session attributes to the given values
    */
	function set_userdata($newdata = array(), $newval = '')
	{
		if (is_string($newdata))
		{
			$newdata = array($newdata => $newval);
		}

		if (count($newdata) > 0)
		{
			foreach ($newdata as $key => $val)
			{
				$_SESSION[$key] = $val;
			}
		}
	}

	/**
    * Erases given session attributes
    */
	function unset_userdata($newdata = array())
	{
		if (is_string($newdata))
		{
			$newdata = array($newdata => '');
		}

		if (count($newdata) > 0)
		{
			foreach ($newdata as $key => $val)
			{
				unset($_SESSION[$key]);
			}
		}
	}

	/**
    * Starts up the session system for current request
    */
	function _sess_run()
	{
		session_start();

		$session_id_ttl = $this->object->config->item('sess_expiration');

		if (is_numeric($session_id_ttl))
		{
			if ($session_id_ttl > 0)
			{
				$this->session_id_ttl = $this->object->config->item('sess_expiration');
			}
			else
			{
				$this->session_id_ttl = (60*60*24*365*2);
			}
		}

		// check if session id needs regeneration
		if ( $this->_session_id_expired() )
		{
			// regenerate session id (session data stays the
			// same, but old session storage is destroyed)
			$this->regenerate_id();
		}

		// delete old flashdata (from last request)
		$this->_flashdata_sweep();

		// mark all new flashdata as old (data will be deleted before next request)
		$this->_flashdata_mark();
	}

	/**
    * Checks if session has expired
    */
	function _session_id_expired()
	{
		if ( !isset( $_SESSION['regenerated'] ) )
		{
			$_SESSION['regenerated'] = time();
			return false;
		}

		$expiry_time = time() - $this->session_id_ttl;

		if ( $_SESSION['regenerated'] <=  $expiry_time )
		{
			return true;
		}

		return false;
	}

	/**
    * Sets "flash" data which will be available only in next request (then it will
    * be deleted from session). You can use it to implement "Save succeeded" messages
    * after redirect.
    */
	function set_flashdata($key, $value)
	{
		$flash_key = $this->flash_key.':new:'.$key;
		$this->set_userdata($flash_key, $value);
	}

	/**
    * Keeps existing "flash" data available to next request.
    */
	function keep_flashdata($key)
	{
		$old_flash_key = $this->flash_key.':old:'.$key;
		$value = $this->userdata($old_flash_key);

		$new_flash_key = $this->flash_key.':new:'.$key;
		$this->set_userdata($new_flash_key, $value);
	}

	/**
    * Returns "flash" data for the given key.
    */
	function flashdata($key)
	{
		$flash_key = $this->flash_key.':old:'.$key;
		return $this->userdata($flash_key);
	}

	/**
    * PRIVATE: Internal method - marks "flash" session attributes as 'old'
    */
	function _flashdata_mark()
	{
		foreach ($_SESSION as $name => $value)
		{
			$parts = explode(':new:', $name);
			if (is_array($parts) && count($parts) == 2)
			{
				$new_name = $this->flash_key.':old:'.$parts[1];
				$this->set_userdata($new_name, $value);
				$this->unset_userdata($name);
			}
		}
	}

	/**
    * PRIVATE: Internal method - removes "flash" session marked as 'old'
    */
	function _flashdata_sweep()
	{
		foreach ($_SESSION as $name => $value)
		{
			$parts = explode(':old:', $name);
			if (is_array($parts) && count($parts) == 2 && $parts[0] == $this->flash_key)
			{
				$this->unset_userdata($name);
			}
		}
	}
}
?>

Comentarios (23)

Gracias por la info, no la sabia

saludos

edgardo

tienes razon, es por eso que buscaba cómo hacerlo de la manera tradicional y afortunadamente encontre este post.

Lo probare, de todos modos Muchas gracias

en que metodo de la libreria de session puedo poner algun codigo para que se ejecute al refrescarse la session. en la libreria nativa de codeigniter estaba el metodo sess_update pero aqui donde puedo poner el codigo? saludos y gracias

Hola!!
En el wiki de CI dice que agreguemos adicionalmente… $config['sess_expiration'] = 7200; al archivo config.php
http://codeigniter.com/wiki/Native_session/

saludos!!

Gracias por la explicación, me ha resultado de mucha ayuda…

saludos

Hola,
Será compatible con codeigniter 2.0 ??

Si, si lo es

Hola que tal, estoy cargando la libreria en el constructor de mi controlador para el login, pero me esta mandando el error de que la sesion ya existe y de ahi no paso, a que se puede deber?

Hola.. yo nuevamente…

Estoy probando la librería con CI 2.0, la copié dentro de “application/libraries” y estoy probando con una libreria de autenticación, específicamente “Ion_Auth”, anteriormente funcionaba bien pero ahora al agregar esta librería de Session me da un error al cestruir una session.

Fatal error: Call to undefined method CI_Session::sess_destroy() in C:\www\application\modules\users\libraries\Ion_auth.php on line 396

fui a la linea especificada y tuve que cambiar la llamada a “$this->ci->session->sess_destroy();” por esta otra: “$this->ci->session->destroy();”, osea eliminar el “sess_” y me anduvo todo bien.

No se si será un error de la libreria Session.php o del Ion_Auth.php ya que segun la documentacion de codeigniter, para destruir una session hay que llamar a sess_destroy() pero con esta nueva libreria hay que omitir el sess_.

Alguna idea??

Saludos

las sesiones en codeigniter 2.0 se siguen trabajando con cookies?

mm si.. sigue trabajando con cookies y tal como dice aquí se recomienda el uso de una base de datos en la documentación

Estoy implementando un site con las vesión 2.0.0 de codeigniter y las sesiones ni tan siquiera funcionan. No podría recuperar los datos escritos por mi en las sesiones. Ha sido meter este ficherito y funcionar correctamente.
¡Saludos!

Saludos, busque en todos lados y esta fue la mejor solución para sesiones nativas en CI-2.0.2 que encontré. Se agradece enormemente el aporte.
p.d.: si me falla seguro posteare por buscar la solución.

saludos ;)

hola nuevamente, probe esta solucion y realmente no fue lo esperado. Me encontre que en IE no funcionaba el logueo de usuarios de mi aplicacion y por suerte se me ocurrio bajar el nivel de seguridad del navegado y voilá! funciona.. es decir sigue funcionando con cookies :S … y la sesion nativa??? hice un debug a la variable $_SESSION y los datos estan registrados.. es decir, si se guardan las cookies te dejo usar $_SESSION…..

alguien tiene alguna solucion o comentario al respecto?. o definitivamente Codeigniter no es mas que una buena intencion :S

saludos

Gracias me has ayudado mucho con esto :D

Hola me gusta tu pagina, que diferencia hay entre este archivo y el que se ve en este link,http://codeigniter.com/wiki/Native_session/ en todo caso me preocupa bastante el tema de las sesiones en CI incluso estoy pensando usar las nativas, probe en una aplicacion de ejemplo y se puede utilizar el:
session_start();
$_SESSION['usuario']=’algo’; y por supuesto hacer condicionales con lo anterior para evitar accesos no deseados, pregunto la factibilidad de esto….

Gracias ….

Hola. hay alguna forma que cuando se venza el tiempo de expiración de sesión se pueda redirigir a otra pagina como la de loguin.
Desde ya Gracias!!!

Buen día:
Estoy usando CI 2.0.2 con HMVC, he tratado de implementar las sesiones nativas porque el navegador de Bill Gates pierde las sesiones de CI y eso provoca problemas serios.
El detalle es que no me funciona correctamente el código publicado, me envía el siguiente error: Fatal error: Class ‘Session’ not found in C:\servidor\htdocs\CItest\application\third_party\MX\Loader.php on line 160

¿Alguién me puede ayudar con esto?

HOLA! TE EQUIVOCAS AL DECIR QUE NO SE PUEDE USAR EL ARREGLO $_SESSION EN CODEIGNITER, UNA COSA NO TIENE QUE VER CON LA OTRA (PHP CONTRA EL FRAMEWORK) FUNCIONA PERFECTAMENTE.

Tomate tu tiempo y piensa lo que acabas de decir

Hola, estoy desarrollando una aplicación con CI 2.03 y tengo un problema, las sesiones simplemente no se destruyen, borro las cookies y sigue logeado, me salgo, borro otra vez las cookies y escribo la ruta en el navegador y vuelve a entrar sin problemas, no se que pasa, he revisado el código y está bien, lo extraño es que si hago eso mismo con el CI y la version 1.7 funciona perfecto. Lo malo es que toda la app está ya desarrollada con el 2.03. Alguien sabe que pueda ser?? será que esta libreria me puede ayudar??.

Lo que dice Dark es cierto.. en codeigniter si se pueden usar las sesiones nativas, es decir el array $_SESSION

que buen aporte!….

con respecto a destruir la sesión hay un pequeño cambio en el nombre de la función.

para destruir la sesión, reemplazar esta sentencia
$this->session->sess_destroy();

por esta:
$this->session->destroy();

o bien modificar la librería sesión, y cambiar el nombre de de la función

saludos mexicanos

Escriba un comentario

*