16
PHP / Secure Sessions
« en: 10 de Junio de 2009, 22:26:11 pm »
Hola phper@s, cuanto tiempo jeje 
Hace poco se me ocurio una idea de crear un sistema de sesiones que se guardan en una base de datos, he pensado que asi el usuario no puede modificar el contenido de la misma y el sistema es mas seguro. La sesiones que vienen por defecto en PHP son las mas seguras pero caducan cuando el usuario cierra el navegador, creo es una de las razones por la que he creado esta funcion
La funcion se llama Secure Sessions
Como funciona?
1. Se crea un cookie en la maquina del cliente con el contenido de un código aleatorio. por ejemplo 12345
3. Se inserta en la base de datos una nueva entrada con el codigo aleatorio y con el contenido de la sesión (por ej: usuario y contraseña)
2. El algoritmo extrae el código de la cookie y lo busca en la base de datos mysql, si lo encuentra guarda el contenido de la sesion en una variable llamada $_SECURE_SESSION
Jeje, para desarollar mas el proyecto primero empezamos con la estructura de la base de datos:
Estructura de la base de datos
Los campos que usara la funcion:
ip: La ip del cliente, creo que no hace falta dar mas detalles
cookie: El nombre del cookie que tiene guardado el usuario en su pc
contain: El contenido de la sesion( usuario, contraseña, un codigo de captcha,etc...)
contain_hash: Es el hash del contenido de la sesion, sirve para no tener que cargar en una variable toda la sesion, mas adelante veremos lo util que es
code: Este es el codigo que se guarda en la cookie, sirve para identificar la sesion en la base de datos.
expire: Es la fecha en formato time cuando caduca la sesion
Uso de Secure Sessions
1. Primero debemos ejecutar la funcion ssession_start, es obligatorio
ssession_start('localhost', 'root', 'password', 'secure_session', 1, 0);
el ultimo y el penultimo parametro son las variables sslimit y sskeeprior
sslimit: el limite de sesiones iguales, por ejemplo para evitar que un usuario inicie sesion de 2 pcs distintos
sskeeprior: en caso de que se supere el sslimit, si esta en 0 se borra la sesion anterior, si esta en 1 no deja crear una sesion nueva con el mismo contenido
En la proxima version voy a mejorar esta caracteristica 
2. Definir una nueva sesion
ssession_new('hispaflog_login', 'id=432;password=12345', time()+3600);
3. Extraer una sesion
ssession_call('hispaflog_login');
echo $_SECURE_SESSION['hispaflog_login'];
4. Eliminar una sesion
ssession_kill('hispaflog_login');
Bueno hasta aqui
, pronto voy a sacar el codigo completo explicado linea a linea
para que otros programadores entiendan el codigo y colaboren con el proyecto 
Aqui el codigo:

Podeis descargar el codigo de aqui tmb: http://www.mediafire.com/?sharekey=046665f6dfc4ddaa61d4646c62b381cbe04e75f6e8ebb871
Este post es un poco chapuza, voy a escribir otro dentro de poco mejor organizado
Bueno, nos vemos en el proximo tutorial
saludos![/code]

Hace poco se me ocurio una idea de crear un sistema de sesiones que se guardan en una base de datos, he pensado que asi el usuario no puede modificar el contenido de la misma y el sistema es mas seguro. La sesiones que vienen por defecto en PHP son las mas seguras pero caducan cuando el usuario cierra el navegador, creo es una de las razones por la que he creado esta funcion
La funcion se llama Secure SessionsComo funciona?
1. Se crea un cookie en la maquina del cliente con el contenido de un código aleatorio. por ejemplo 12345
3. Se inserta en la base de datos una nueva entrada con el codigo aleatorio y con el contenido de la sesión (por ej: usuario y contraseña)
2. El algoritmo extrae el código de la cookie y lo busca en la base de datos mysql, si lo encuentra guarda el contenido de la sesion en una variable llamada $_SECURE_SESSION
Jeje, para desarollar mas el proyecto primero empezamos con la estructura de la base de datos:
Estructura de la base de datos
Los campos que usara la funcion:
ip: La ip del cliente, creo que no hace falta dar mas detalles
cookie: El nombre del cookie que tiene guardado el usuario en su pc
contain: El contenido de la sesion( usuario, contraseña, un codigo de captcha,etc...)
contain_hash: Es el hash del contenido de la sesion, sirve para no tener que cargar en una variable toda la sesion, mas adelante veremos lo util que es

code: Este es el codigo que se guarda en la cookie, sirve para identificar la sesion en la base de datos.
expire: Es la fecha en formato time cuando caduca la sesion

Uso de Secure Sessions
1. Primero debemos ejecutar la funcion ssession_start, es obligatorio
ssession_start('localhost', 'root', 'password', 'secure_session', 1, 0);
el ultimo y el penultimo parametro son las variables sslimit y sskeeprior
sslimit: el limite de sesiones iguales, por ejemplo para evitar que un usuario inicie sesion de 2 pcs distintos
sskeeprior: en caso de que se supere el sslimit, si esta en 0 se borra la sesion anterior, si esta en 1 no deja crear una sesion nueva con el mismo contenido
En la proxima version voy a mejorar esta caracteristica 
2. Definir una nueva sesion
ssession_new('hispaflog_login', 'id=432;password=12345', time()+3600);
3. Extraer una sesion
ssession_call('hispaflog_login');
echo $_SECURE_SESSION['hispaflog_login'];
4. Eliminar una sesion
ssession_kill('hispaflog_login');
Bueno hasta aqui
, pronto voy a sacar el codigo completo explicado linea a linea
para que otros programadores entiendan el codigo y colaboren con el proyecto 
Aqui el codigo:
Código: [Seleccionar]
function ssession_start($host, $user, $password, $db, $table='ssessions', $sstlimit=5, $sskeeprior=0) {
if(!@mysql_connect($host, $user, $password)) { //Se comprueba si la conexion a la base de datos mysql es correcta
trigger_error('La conexion a la base de datos mysql falla',E_USER_WARNING); //sino nos muestra un error
} else if(!@mysql_select_db($db)) {
trigger_error('No se puede seleccionar la base de datos <b>'.$db.'</b>',E_USER_WARNING); //Ahora comprobamos si se puede seleccionar la base de datos, sino nos muestra error
}
// ejecutamos todas estas funciones:
ssession_tools($table, $sslimit, $sskeeprior); //Esta funcion sirve para definir variables necesarias para el funcionamiento de nuestro codigo
ssession_check(); //Esta funcion comprueba errores, comprueba si la sesion ha caducado, etc...
ssession_clean(); //Esta funcion hace un poco de limpieza en la base de datos
}
function ssession_tools($tablename, $sslimit, $sskeeprior) {
global $ssesconfig;
global $minissdfexpvar;
$ssesconfig = array("table" => $tablename, "defaultexpire" => "600", "sslimit" => $sslimit, "sskeeprior" => $sskeeprior,); //se define la variable $ssesconfig, como vemos esta variable define algunos valores como el nombre de la tabla y el tiempo por defecto en la cual una sesion caduca
}
function ssession_check() {
global $ssesconfig;
global $ssession_check_mysql_error;
$sql = mysql_query("SELECT * FROM ".$ssesconfig['table']); //se comprueba que la tabla existe
if(!$sql) {
trigger_error('La tabla <b>'.$ssesconfig['table'].'</b> esta danada o no existe',E_USER_ERROR);
}
}
function ssession_clean() {
//esta funcion es muy util, aqui se comprueba si hay sesiones duplicadas en la base de datos, si es asi las borra
global $ssesconfig;
global $ssession_clean_mysql_error;
$sql = mysql_query("SELECT * FROM ".$ssesconfig['table']); //hacemos un query de todas las sesiones
while($clean=mysql_fetch_array($sql)) {
if(md5($clean['contain'])!=$clean['contain_hash']) {
ssession_kill($clean['cookie']);
}
if($clean[expire]<=time()) { //Aqui comprobamos si la sesion ha caducado, si es asi se elimina de la base de datos
if(!mysql_query("DELETE FROM ".$ssesconfig['table']." WHERE id='$clean[id]'")) {
trigger_error('Ha fallado el sistema de caducacion de sesiones, la sesion caducada no ha sido eliminada! Se procedera a su eliminacion en la proxima ejecucion.',E_USER_WARNING);
$ssession_call_mysql_error = mysql_error();
}
}
$WHERE = "WHERE contain_hash='".$clean[contain_hash]."'";
global $fclean;
$fclean = mysql_num_rows(mysql_query("SELECT * FROM ".$ssesconfig['table']." ".$WHERE));
if($fclean>$ssesconfig['sslimit']) {
if(!mysql_query("DELETE FROM ".$ssesconfig['table']." ".$WHERE." AND ip!='$_SERVER[REMOTE_ADDR]' LIMIT 1")) { //se elimina
trigger_error('Ha fallado el sistema de limpieza de sesiones, la limpieza no ha sido llevada a cabo correctamente! Se procedera a relimpiar en la proxima ejecucion.',E_USER_WARNING); //si falla la eliminacion, se muestra un error
$ssession_clean_mysql_error = mysql_error();
}
}
}
}
function ssession_sqlblind($char) {
$char = mysql_real_escape_string($char);
return $char;
}
function ssession_call($cookie) {
global $ssession_call_error;
global $ssesconfig;
global $_SECURE_SESSION;
global $_SECURE_SESSION_CODE;
global $_SECURE_SESSION_IP;
global $_SECURE_SESSION_EXPIRE;
$_SSES = array();
$cookievar = ssession_sqlblind($_COOKIE[$cookie]);
$sql = mysql_query("SELECT * FROM ".$ssesconfig['table']." WHERE code='$cookievar'");
while($ssext=mysql_fetch_array($sql)) {
if($ssext[ip]!=$_SERVER['REMOTE_ADDR']) {
ssession_kill($ssext[cookie]);
trigger_error('The ip not match',E_USER_WARNING);
}
$ssext_cookie = $ssext[cookie];
$_SECURE_SESSION[$ssext_cookie] = $ssext[contain];
$_SECURE_SESSION_EXPIRE[$ssext_cookie] = $ssext[expire];
$_SECURE_SESSION_IP[$ssext_cookie] = $ssext[ip];
$_SECURE_SESSION_CODE[$ssext_cookie] = $ssext[code];
}
$ssession_call_error = mysql_error();
}
function ssession_new($cookie, $contain=NULL, $expire=NULL) {
global $ssession_new_mysql_error;
global $ssesconfig;
global $sslimit;
if($expire==NULL) {
$expire = time() + $ssesconfig[defaultexpire];
}
$code = md5(mt_rand().time().$_SERVER['REMOTE_ADDR'].$_SERVER['HTTP_USER_AGENT'].mt_rand());
$contain_hash = md5($contain);
$uniqses = mysql_num_rows(mysql_query("SELECT * FROM ".$ssesconfig['table']." WHERE contain_hash='$contain_hash'"));
if($uniqses>$sslimit AND $ssesconfig['sskeeprior']==1) {
trigger_error('Lo sentimos, el limite de sesiones unicas ha sido superado', E_USER_NOTICE);
} else if($uniqses>$sslimit AND $ssesconfig['sskeeprior']==0) {
if(mysql_query("DELETE FROM ".$ssesconfig['table']." WHERE contain_hash='$contain_hash' LIMIT 1")) {
ssession_new($cookie, $contain, $expire);
} else {
trigger_error('Imposible crear la sesion', E_USER_NOTICE);
}
} else if(!mysql_query("INSERT INTO ".$ssesconfig['table']." (`ip` ,`cookie` ,`code` ,`contain` ,`contain_hash` ,`expire`) VALUES ('$_SERVER[REMOTE_ADDR]', '$cookie', '$code', '$contain','$contain_hash' , '$expire')")) {
trigger_error('Ha fallado la creacion de la sesion en el servidor', E_USER_WARNING);
} else if(!setcookie($cookie, $code, $expire)) {
trigger_error('Ha fallado la creacion del cookie en el cliente', E_USER_WARNING);
if(!mysql_query("DELETE FROM ".$ssesconfig['table']." WHERE code='$code'")) {
trigger_error('Ha fallado la eliminacion de la sesion creada.', E_USER_WARNING);
}
}
$ssession_new_mysql_error = mysql_error();
}
function ssession_kill ($cookie) {
global $ssesconfig;
global $ssession_kill_mysql_error;
global $_SECURE_SESSION_CODE;
if(!mysql_query("DELETE FROM ".$ssesconfig['table']." WHERE cookie='$cookie' AND ip='$_SERVER[REMOTE_ADDR]' AND code='$_SECURE_SESSION_CODE[$cookie]'")) {
trigger_error('function ssession_check(): Ha fallado la eliminacion de la sesion en el servidor', E_USER_WARNING);
$ssession_kill_mysql_error = mysql_error();
} else if(!setcookie($cookie, time()+$ssesconfig['defaultexpire'])) {
trigger_error('function ssession_check(): Ha fallado la eliminacion del cookie', E_USER_WARNING);
}
}
?>Jejjejeje yap esta, funciona de maravilla 
Podeis descargar el codigo de aqui tmb: http://www.mediafire.com/?sharekey=046665f6dfc4ddaa61d4646c62b381cbe04e75f6e8ebb871
Este post es un poco chapuza, voy a escribir otro dentro de poco mejor organizado

Bueno, nos vemos en el proximo tutorial
saludos![/code]



