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.
