Primero está este formulario común y corriente para logear el empleado:
Código HTML :
<form name="master_key" id="master_key" action="wellcome.php" method="post" onsubmit="crypt()" class="form-signin"> <h2 class="form-signin-heading">Inicia Sesión</h2> <label for="inputEmail" class="sr-only">Usuario</label> <input type="text" id="inputUser" class="form-control" placeholder="Usuario" name="user" value="<? print($user); ?>" required autofocus> <label for="inputPassword" class="sr-only">Contraseña</label> <input type="password" id="key" class="form-control" placeholder="Contraseña" name="key" required> <button class="btn btn-lg btn-primary btn-block" type="submit">Entrar</button> </form>
Tiene una peculiaridad, para no dejar el paso de la clave se encripta en MD5 desde el DOM.
Después de esto, llega a la página que hace la recuperación de los datos de MySQL:
Código PHP :
<?php session_start(); require_once('functions/token.php'); require_once('functions/conect_bd.php'); require_once('functions/nivel.php'); require_once('functions/user_acces.php'); require_once('functions/global_vars.php'); require_once('class/strings.class.php'); mysql_select_db($_SESSION['db_intranet']); $string = new strings(); $user=var_segura($_POST['user']); $user = $string->lowercase_string($user); $pass=var_segura($_POST['key']); //} function check_rec($value){ global $user; global $pass; if($value==1){ setcookie("user", $user, time()+3600*24*7); setcookie("pass", $pass, time()+3600*24*7); } } if($_POST['user']==NULL){ print($e2); }else{ if($_POST['key']=='d41d8cd98f00b204e9800998ecf8427e'){ print($e2); }else{ if(isset($_POST['rec'])==1){ check_rec($_POST['rec']); } $token=token(); acces(); registro(); check_level($user); header ('Location: intranet.php?k='.$token); } } ?>
primero reviso la entrada del empleado con "var_segura" que es un simple "addslashes(trim($))", después si el user y pass son diferentes a "NULL" genero una cookie para guardar el recorrido del usuario, después se hace la validación del login, se guardan los datos de quien accede a la app y posteriormente se hace la consulta del nivel de usuario para pasar a la plataforma, es aquí donde el "token" lo genero y paso de pagina en pagina con la función token. Éste sistema ha implicado que no se pueda recargar la página a no ser por una petición de la misma app.
La función token:
Código PHP :
<? function cryptoken($c,$d){ $a=crypt($c,$d); $b=sha1(md5($a)); return $b; } function checktoken(){ $a=$_SESSION['ktoken']; $b=$_SESSION['rtoken']; $c=$_GET['k']; $d=cryptoken($a,$b); if($c===$d){ return true; }else{ return false; } } function token(){ for($a=1;$a<=10;$a++){ $b[] = rand(0,9); } $c=$b[0].$b[1].$b[2].$b[3].$b[4].$b[5].$b[6].$b[7].$b[8].$b[9]; $_SESSION['ktoken']=$c; $d=uniqid(rand(0,9)); $_SESSION['rtoken']=$d; return cryptoken($c,$d); } ?>
La función user_acces:
Código PHP :
<?php function check(){ global $user; global $pass; global $token; $up=mysql_query("UPDATE users SET nombre='".$user."', pass='".$pass."', llave='".$token."', ip_acceso='".$_SERVER['REMOTE_ADDR']."', fecha_acceso='".date("Y/m/d")."', nivel='".$_SESSION['nivel']."', seguro='".$_SESSION['seguro']."', id='".$_SESSION['id']."', hora_acceso='".date("H:i:s")."', sesion_duracion='".date("H:i:s")."' WHERE nombre='".$user."'"); } function acces(){ global $user; global $pass; global $e1; global $e2; mysql_select_db($_SESSION['db_intranet']); $check = mysql_query("SELECT nombre FROM users WHERE nombre='".$user."'") or die($e1); $result_check = mysql_fetch_array($check); if($result_check[0]==$user){ $check = mysql_query("SELECT pass FROM users WHERE nombre='".$user."'") or die($e1); $result_check = mysql_fetch_array($check); if($result_check[0]==$pass){ $check = mysql_query("SELECT nombre, pass, llave, ip_acceso, fecha_acceso, nivel, seguro, id, hora_acceso, sesion_duracion, id_user FROM users WHERE nombre='".$user."'") or die($e1); $checkDetails = mysql_query("SELECT * FROM users_details WHERE usuario='".$user."'") or die($e1); $r_ch= mysql_fetch_array($check); $r_dt=mysql_fetch_array($checkDetails); $_SESSION['nombre']=$r_ch[0]; $_SESSION['pass']=$r_ch[1]; $_SESSION['ip_acceso']=$r_ch[3]; $_SESSION['fecha_acceso']=$r_ch[4]; $_SESSION['nivel']=$r_ch[5]; $_SESSION['seguro']=$r_ch[6]; $_SESSION['id']=$r_ch[7]; $_SESSION['hora_acceso']=$r_ch[8]; $_SESSION['sesion_duracion']=$r_ch[9]; $_SESSION['nombres']=$r_dt[1]; $_SESSION['apellidos']=$r_dt[2]; $_SESSION['correo']=$r_dt[3]; $_SESSION['key_user']=$r_ch[10]; $_SESSION['tienda']=$r_dt['tienda']; check(); }else{ exit($e2); } }else{ exit($e2); } } function registro(){ $a=$_SESSION['nombre']; $b=$_SESSION['nombres']; $c=$_SERVER['SERVER_SOFTWARE'].'*'.$_SERVER['HTTP_CONNECTION'].'*'.$_SERVER['SERVER_PROTOCOL'].'*'.$_SERVER['DOCUMENT_ROOT'].'*'.$_SERVER['SCRIPT_NAME'].'*'.$_SERVER['QUERY_STRING'].'*'.$_SERVER['GATEWAY_INTERFACE']; $d=date('Y/m/d'); $e=date('H:i:s'); $f=$_SERVER['REMOTE_ADDR']; $g=$_SERVER['HTTP_USER_AGENT']; $h="INSERT INTO registro_entrada (usuario, nombre, llave, fecha, hora, ip, plataforma) VALUES ('$a', '$b', '$c', '$d', '$e', '$f', '$g');"; $i=mysql_query($h); } ?>
Conecto a BDD de forma arcaica, lo sé, con este patrón que de hecho estaba aquí en clab:
Código PHP :
<?php class conectarDB{ private static $_singleton; private $_conexion; private function __construct(){ require_once('config.php'); $this->_conexion=mysql_connect($host, $user_raiz, $clave, $puerto); } public static function instanciar(){ if (is_null(self::$_singleton)){ self::$_singleton = new conectarDB(); } return self::$_singleton; } } $DBobj = conectarDB::instanciar(); ?>
Pues éste es el sistema que implemente hace 6 años, quisiera tener sus opiniones y más que nada sus críticas, acerca de este filtro de seguridad.