Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   PHP (https://www.clubdelphi.com/foros/forumdisplay.php?f=15)
-   -   validar usuarios de forma correcta (https://www.clubdelphi.com/foros/showthread.php?t=65651)

hibero 03-01-2010 21:33:41

validar usuarios de forma correcta
 
pretendo que los usuarios se validen antes de entrar a mi sitio web. Los pares usuario/contraseña estarán almacenados en un tabla llamada usuarios dentro de una base de datos MySQL.

Código SQL [-]
  Create table usuarios(
     usuario varchar(20) not null primary key,
     passwd varchar(20) not null,
  );

tendré 3 ficheros

login.php : contendrá el formulario html donde se introducirá el usuario y la contraseña. Al hacer clic sobre el boton se enviará el formulario utilizando POST al script php autenticacion

Código PHP:

<form action="autenticacion.php" method="POST">
   
usuario:<input name="usuario" size="25" value=""/>
   
Contraseña:<input name="passwd" size="25" type="password"/>
   <
input type="submit" value="Inicio de sesión"/>
</
form

autenticacion.php: en este script se comprueba si el par usuario/contraseña suminisgtrado por el usuario coinciden con los almacenados en la base de datos

Código PHP:


  
if (login($_POST["usuario"],$_POST["passwd"])==1){
 
//Si coninciden usuario y congtraseña
    
session_start(); //iniciamos la sesion
    
$_SESSION["logeado"]=1//creamos una variable logeado=1 (1)
    
$_SESSION["usuario"]=$_POST["usuario"]; 
/*almaceno el usuario como variable de sesion para utilizarlo luego en mi aplicacion*/
    
header ("Location: index.php"); //todo es correcto estoy validado abro mi aplicacion web
:cool:  }
   else {
     
//si no existe se va a login.php
     
header("Location: login.php");
   }

/*esta funcion devuelve 1 si el par usuario/contraseña coinciden con los almacenados en la base de datos. Utilizo PDO para conectar con la base de datos. Además uso una consulta paramétrica para evitar SQLInjection
*/
  
function login($usuario,$passwd){
     
/*asignar valores pertinentes al crear el objeto PDO en mi caso prueba*/ 
     
$db = new PDO("mysql:host=localhost;dbname=prueba",'prueba','prueba');
     
$q $db->prepare("SELECT passwd from usuarios where usuario=:usuario");
     
$q->bindParam(':usuario',$usuario);
     
$q->execute();
     
$row $q->fetch(PDO::FETCH_ASSOC);
     if (
$row["passwd"]=="" || $row["passwd"]!=$passwd){
         return 
0// usuario/contraseña incorrecta
     
}
         else return 
1// usuario/contraseña correcta
     
$db=null;
  } 

(1) la variable logeado por motivos de seguridad debe reemplazar por una variable con un nombre más complicado por ejemplo "123AWETRT323esdaqwe" pero para no liarla mas usare "logeado"

seguridad.php: para evitar que alguien pueda ejecutar mi aplicacion(index.php) sin previamente haberse validado se incluirá seguridad php al principio de index.php de forma que sea lo primero que se ejecute

Código PHP:

<?php
    session_start
(); //inicio sesion

    
if ($_SESSION["logeado"] !=1) { //no estoy logeado debo logearme primero
       
header("Location: login.php");
       exit();
    }
      
//en caso contrario estoy logeado y puedo continuar con la aplicacion
?>

En todos los ficheros de mi aplicacion tendrán una primera linea como la siguiente para comprobar la seguridad

Código PHP:

   <?php  include("seguridad.php");   ?>

Esta forma de asegurar una aplicación la he encontrado googleando por ahi.

¿Qué se puede mejorar?
¿Qúe incluiriais?
¿Hay una forma de permitir sólamente 3 intentos?. Se me ocurre que agregando un nuevo campo en la base de datos numfallos, fecha,hora y que desde que se llegue a un número de fallos predeterminado que se bloquee durante un periodo de tiempo determinado desde fecha hora el usuario podría ser una mejora para eviar que alguien utilice un programa para hacer tropocientos intentos
¿es suficiente el uso de una consulta parametrica para evitar SQLInjection?

salu2 y gracias

Julián 04-01-2010 12:16:32

Jau!

Cita:

Empezado por hibero (Mensaje 349939)
¿es suficiente el uso de una consulta parametrica para evitar SQLInjection?

Pues no lo sé por que no las uso ni creo que lo vaya a hacer en el futuro, pero sin saberlo, me apostaría mi pijama de Chuck Norris a que no.

Debes comprobar que los valores recibidos en $_GET son válidos y no contienen cosas raras como código que pueda servir para hacer sql injecting o ataques xss. Es decir, antes de ejecutar el SELECT nos aseguramos de que las variables usuario y password contienen unicamente letras y dígitos, por ejemplo, y que no tengan caracteres como <,#,?,",', etc.
Para esto lo mejor sería usar un script de probada eficacia como Kses o PHPIDS.

Cita:

Empezado por hibero (Mensaje 349939)
¿Qué se puede mejorar?

La lógica que usas es "si el user no está autentificado no lo dejo entrar". Creo que sería mejor "Le dejo entrar si está autentificado". Es decir, que la opción por omisión debería ser no dejar entrar, pues si de alguna forma alguien consigue anular lo que hubiera en seguridad.php, por ejemplo sustituyendo dicho archivo no podría ir a ningún sitio. No se si este punto me ha quedado claro.

Cita:

Empezado por hibero (Mensaje 349939)
¿Qúe incluiriais?

El funcionamiento de seguridad.php debería ser el siguiente:
session_start;
if ($autentificado)
include('user.php');
else
include(login.php);

Teniendo en user.php el típico código que pone "hola fulanito" con los enlaces o botones para cerrar sesión, ver perfil, etc. Y en login.php el form con los inputs para user y password y si acaso otro botón o enlace para "recordar contraseña"

Ademas de eso en cada página, despues del seguridad.php deberias permitir unas cosas u otras en función de los derechos de acceso del uaurio, para lo cual deberías disponer de un sistema de permisos, con usuarios, roles, grupos, etc.

Lo del nombre de la variable logueado no le veo mucho sentido. En mis scripts dicha variable es booleana. Claro, que un usuario, además de poder tener true o false en "logueado" tambien tiene otra variable "userlevel" que le permite mas o menos privilegios. O sea, que un user con "logueado==true" cuyo userlevel sea el "level por omisión" es practicamente un "invitado" y poco puede hacer hasta que no se le hayan otorgado derechos de acceso a alguna parte o adjudicado algún rol o adscrito a algún grupo.

Cita:

Empezado por hibero (Mensaje 349939)
¿Hay una forma de permitir sólamente 3 intentos?. Se me ocurre que agregando un nuevo campo en la base de datos numfallos, fecha,hora y que desde que se llegue a un número de fallos predeterminado que se bloquee durante un periodo de tiempo determinado desde fecha hora el usuario podría ser una mejora para eviar que alguien utilice un programa para hacer tropocientos intentos

Lo de los intentos y el ampliar el tiempo entre ellos me parece cosa obligada y yo lo que hago es guardar los intentos asociados a la dirección IP, la cual, puedo llegar a meter en un filtro si hace falta.



Gueno, menudo rollo he largao, XDD

hibero 04-01-2010 15:41:23

Se que utilizar paràmetros en las consultas no soluciona todo (puede ser la constumbre de utilizarlas en delphi, "la cabra tira al monte"), pero sin tan solo se encaerga de asignar el tipo de datos correctos, pondrá más dificil . Además como comentas hay que revisar todas las variables que me pasen tanto por GET como por POST (no hay que fiarse nunca de un usuario). No conocía las librerias que mencionas pero voy a probarlas y supongo que acabarlas integrando en todo el proyecto.
el fichero seguridad.php está pensado para que en cada fichero php del proyecto incluir nada más empezar un include('seguridad.php'); de forma
que se comprueba la seguridad con solo incluir este include.
lo del nombre de la variable, es que lo lei por ahí,decidí incluirlo para ver si añgien me lo aclaraba.
En cuanto a limitar el acceso desde una dirección ip, me parece buena idea, pero que pasa si bloqueas un usurio que te entra desde la ip tal,¿No estarías bloqueando a todos los usuarios que están tras el mismo router ya que todos salen con la misma ip?

De rollo nada me has dado bastantes ideas,

salu2

hibero 04-01-2010 15:47:04

se me acaba de ocurrir otra posible mejora, almacenar la passwd encriptada en la base de datos. Podría utilizar la funcion md5 de php

http://php.net/manual/en/function.md5.php

Salu2


La franja horaria es GMT +2. Ahora son las 00:29:38.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi