Hace un tiempito hablamos de una manera rápida y básica de armar la autenticación de usuarios en CodeIgniter(CI), esto se puede mejorar mucho, la idea es almacenar las sesiones en la base de datos para las validaciones constantes de la sesión, que realizarÃa un proceso vigilante.
- La base de datos:
En el post inicial ya tenemos una estructura de base de datos, una tabla usuarios y una de tipo de usuarios. CI nos permite salvar las sesiones automáticamente en tablas (si se lo indicamos), para ello debemos crearla previamente:
CREATE TABLE IF NOT EXISTS ci_sesion ( session_id varchar(40) DEFAULT '0' NOT NULL, ip_address varchar(16) DEFAULT '0' NOT NULL, user_agent varchar(120) NOT NULL, last_activity int(10) unsigned DEFAULT 0 NOT NULL, user_data text NOT NULL, PRIMARY KEY (session_id) );
Configuramos la sesión, nos vamos a codeigniter --> application --> config --> config.php
Clic aquà para mostrar/ocultar el código
// El nombre que quiere que la cookie de sesión sea guardada. $config['sess_cookie_name'] = 'ci_session'; // El número de segundos que quiere que dure la sesión. $config['sess_expiration'] = 7200; // Si la sesión expira al cerrar el navegador $config['sess_expire_on_close'] = TRUE; // Si encriptar o no los datos de sesión. $config['sess_encrypt_cookie'] = FALSE; // Si guardar los datos de sesión a una base de datos. // Debe crear la tabla antes de habilitar esta opción. $config['sess_use_database'] = TRUE; // El nombre de la tabla de sesión en la base de datos // Debe ser un nombre de tabla válido en SQL $config['sess_table_name'] = 'ci_sesion'; // Se indica que valide si coincide la dirección de IP // del usuario cuando se lean los datos de sesión. // Si la IP es dinámica y se requiere una sesión ilimitada // deberá establecerlo a FALSE. $config['sess_match_ip'] = FALSE; // Si coincide el Agente del Usuario cuando se leen // los datos de sesión. $config['sess_match_useragent'] = TRUE; // Indica cuan a menudo la clase de sesión se regenerará // y creará un nuevo identificador de sesión. $config['sess_time_to_update'] = 300; // indicamos si queremos controlar el // tiempo limite de expiracion al iniciar sesion $config['sess_use_time_expire'] = TRUE;
- Aplicando los hooks a nuestras sesiones:
En CI podemos trabajar con hooks, lo que nos permite disparar rutinas en momentos especÃficos del sistema:
pre_system: se dispara al principio de la ejecución del sistema.
pre_controller: se dispara antes de cargar el controlador.
post_controller_constructor: se dispara luego de cargar el constructor del controlador (recordemos que el constructor de una clase es lo primero que se ejecuta en ella).
post_controller: se dispara luego de que el controlador se haya cargado.
post_system: se dispara al final de la ejecución del sistema.
pre_controller: se dispara antes de cargar el controlador.
post_controller_constructor: se dispara luego de cargar el constructor del controlador (recordemos que el constructor de una clase es lo primero que se ejecuta en ella).
post_controller: se dispara luego de que el controlador se haya cargado.
post_system: se dispara al final de la ejecución del sistema.
A nosotros nos interesa ejecutar nuestro proceso de validación de sesión, luego de que se cargue el constructor del controlador donde estemos en ese momento, asà que usaremos post_controller_constructor, editamos el archivo hook.php, nos vamos a codeigniter --> application --> config --> hook.php y agregamos lo siguiente:
hook.php:
$hook['post_controller_constructor'] = array( 'class' => 'gestion_sesion', // clase que controla la sesion 'function' => 'index', // metodo encargado de todo, dentro de la clase 'filename' => 'gestion_sesion.php', // archivo a cargar 'filepath' => 'hooks' // carpeta donde se encuentra la clase );
Ahora debemos crear la clase, nos vamos a codeigniter --> application --> hooks y creamos un archivo con el nombre gestion_sesion.php que es el que asignamos:
gestion_sesion.php:
Clic aquà para mostrar/ocultar el código
<?php class Gestion_sesion{ function index(){ //instanciamos al objeto codeigniter $CI =& get_instance(); // obtenemos el nombre del controlador en el que estamos $controlador = $CI->router->class; // indicamos los controladores que pueden ver por defecto los visitantes $controladores_guest = array('index_c','login_c'); // si la sesion se inicio y el usuario intenta entrar a login_c, // lo enviamos al index if(user_is_logged() && $controlador=='login_c'){ redirect('index_c'); // si el usuario es un visitante, // solo puede entrar a los controladores permitidos para él.. }elseif(!user_is_logged() && (!in_array($controlador,$controladores_guest))){ redirect('login_c'); // cerramos la sesion si el tiempo establecido expiro // solo si se cambio el tiempo de expiracion }elseif($CI->config->item('sess_use_time_expire')){ // cargamos la libreria de sesion $CI->load->library('session'); $arrSesion = $CI->session->userdata('ses_usuario'); if (is_array($arrSesion) and $arrSesion['seslimite']<=time()){ cerrar_sesion(); } } unset($CI); } } ?>
Por ultimo en esto de los hooks, hay que indicarle a CI que deseamos que se apliquen estos cambios, asà que nos vamos a codeigniter --> application --> config --> config.php y donde dice:
$config['enable_hooks'] = FALSE;
lo cambiamos por:
$config['enable_hooks'] = TRUE;
En la clase gestion_sesion.php hacemos uso de unas funciones que no son nativas de PHP, asà que creamos nuestro propio helper(asistente) y ahà las incluimos, esto lo hacemos asà porque al ser un asistente, podemos acceder a esas funciones cuando lo necesitemos. Nos vamos a codeigniter --> system -->helpers y ahà creamos un archivo de nombre mod_ppal_helper.php, puedes usar cualquier otro nombre, pero deja el sufijo _helper, dentro del archivo incluimos nuestras funciones:
mod_ppal_helper.php:
Clic aquà para mostrar/ocultar el código
<?php # determina si el usuario esta logueado o no.. if ( ! function_exists('user_is_logged')) { function user_is_logged(){ //instanciamos al objeto codeigniter $CI =& get_instance(); // cargamos la base de datos $CI->load->database('default'); // obtenemos el valor del item 'sess_use_database' $sess_use_database = $CI->config->item('sess_use_database'); // cargamos la libreria de sesion $CI->load->library('session'); // obtenemos los datos de la sesion $arrSesion = $CI->session->userdata('ses_usuario'); // si no esta definida la sesion, no esta logueado if (!isset($arrSesion['usuario'])){ return false;// indicamos no is_logged }else{ // obtenemos el id del usuario $session_id = $CI->session->userdata('session_id'); // si se usa la session database, debemos asegurarnos // de que la sesion en el cliente, coincida con // la sesion de la base de datos if (!empty($session_id) and $sess_use_database){ // consultamos por id $CI->db->from('ci_sesion'); $CI->db->where('session_id',$session_id); $query = $CI->db->get(); // si coincide el session_id en algun registro // es porque el usuario tiene sesion abierta return ($query->num_rows()>0) ? true : false; }else{ // return (!empty($session_id)) ? true : false; } } $CI->db->close(); unset($CI); } } # permite cerrar la sesion activa .. if (! function_exists('cerrar_sesion')){ function cerrar_sesion(){ //instanciamos al objeto codeigniter $CI =& get_instance(); // cargamos la base de datos $CI->load->database('default'); // obtenemos el valor del item 'sess_use_database' $sess_use_database = $CI->config->item('sess_use_database'); // si el usuario esta logueado, cerramos la sesion.. if (user_is_logged()){ // cargamos la libreria sesion $CI->load->library('session'); // si se esta usando la base de datos para las sesiones if($sess_use_database){ //exit('entre, esta logueado y se usa db'); // indicara si se elimino la seison de la db $delete = false; // obtenemos los datos de la sesion $arrSesion = $CI->session->userdata('ses_usuario'); // obtenemos los registros de sesion $CI->db->select('user_data,session_id'); $CI->db->from('ci_sesion'); $query = $CI->db->get(); $arrDatos = array(); // recorremos la lista de usuarios con sesion en la db foreach($query->result() as $row){ // obtenemos el user_data de la fila $valor = $row->user_data; // los datos estan serializados en la db // asi que los deserializamos $arrData = unserialize($valor); // verificamos si el usuario pasado por parametro // es el mismo q tiene la sesion abierta if ($arrSesion['usuario']==$arrData['ses_usuario']['usuario']){ // borramos la sesion de la db $CI->db->delete('ci_sesion',array('session_id' => $row->session_id)); //echo $CI->db->last_query();exit; $delete = true; break; } } if($delete){ // cerramos la sesion $CI->session->sess_destroy(); } }else{ // cerramos la sesión $CI->session->sess_destroy(); } } // adicionalmente verificamos las sesioens activas en la db // y eliminamos las que tengan determinado tiempo de incactividad $CI->db->where('last_activity <',(time() - 3600));//3600 - 1 hora $CI->db->delete('ci_sesion'); $CI->db->close(); #----------------------------------------------------------------------- unset($CI); // redireccionamos al controlador index redirect('index_c', 'location'); } } ?>
Ahora le indicamos a CI que cargue por defecto nuestro helper, ya que son funciones de uso común. En codeigniter --> application --> config --> autoload.php agregamos el helper al array:
$autoload['helper'] = array('url');
nos quedarÃa asÃ:
$autoload['helper'] = array('url','mod_ppal');
Muchas gracias Reinaldo por compartir el código, muy interesante y provechoso.
ResponderEliminarSaludos desde el otro lado del charcho,
http://www.bonisoft.com
Disculpa, quiero leer el articulo completo, como le hago?
ResponderEliminarhola: http://cassianinet.blogspot.com.es/2012/06/codeigniter-sesiones-hook-y-base-de.html
ResponderEliminar