PHP Validando usuarios
Revisión del 08:58 20 nov 2023 de Angelfg (discusión | contribuciones)
Sumario
Introdución
- Un aspecto ao que case sempre imos enfrontarnos é ao de permitir o acceso a certas páxinas en función dos permisos que teña un determinado cliente.
- Para obter ditos permisos teremos que validar ao usuario e identificalo.
- A identificación case sempre vai vir dun formulario no que o usuario introduce o seu login-password.
- Nos recollemos ditos datos e normalmente faremos unha consulta a unha base de datos para comprobar que o usuario existe.
- Neste punto imos ver como podemos facer para que o usuario non poida entrar nas páxinas se non está validado.
- Como aínda non sabemos 'conectar' con bases de datos imos supoñer que o usuario ten que ter de nome 'pepe' e de password '12345'. En caso doutra combinación supoñemos que o usuario non está autorizado para acceder ao sitio web.
- Fixarse que estamos implementando un mecanismo de autenticación de usuarios.
- Non indicamos nada acerca dos permisos que ten dito usuario. Por exemplo, un administrador e un usuario son usuarios que teñen dereito de conexión ao sitio web, pero cada un deles terá permisos diferentes para poder realizar accións distintas...
- IMPORTANTE: Durante o proceso de autenticación, o navegador envía ao servidor o usuario/password introducido polo usuario. Eses datos deben ir cifrados para que non poidan ser obtidos de forma fraudulenta pola rede. Para iso é necesario empregar certificados dixitais que no caso das páxinas web, tradúcese en empregar unha conexión https no que o servidor web emite un certificado dixital váliado que o indentifica.
- Nunca se debe desenvolver unha aplicación web no que non se empregue este tipo de certificado.
- Como facelo queda fora dos contidos deste curso, polo que as probas que estades a desenvolver empregan conexións non seguras de tipo http.
Exemplo rexistro/validación de usuario e carrito da compra
- Imos facer un pequeno sitio web no que imos poder rexistar novos usuarios e despois mediante unha validación imos poder ter acceso as páxinas para mercar produtos e xestionar un carrito da compra
Rexistro de usuarios
- Nesta páxina vaise amosar un login/password e vaise rexistrar un usuario/password.
- Primeiro temos que crear a táboa usuarios no Mysql:
1 CREATE TABLE `php`.`usuarios` ( 2 `id` INT NOT NULL AUTO_INCREMENT, 3 `login` VARCHAR(50) NOT NULL, 4 `password` VARCHAR(255) NOT NULL, 5 PRIMARY KEY (`id`), 6 UNIQUE INDEX `login_UNIQUE` (`login` ASC) VISIBLE);
- Nesta táboa o password vai estar encriptado cunha función de hash que en principio devolve como mínimo 60 caracteres, pero que pode chegar a devolver ata 255 caracteres, por se nun futuro cambia a implementación.
- Agora necesitamos gardar usuarios/password nesa táboa. Para iso imos facer uso das funcións:
- password_hash() => Para gardar a contrasinal
- password_veriry() => Para comprobar a contrasinal
- Engadimos ao arquivo bd.inc.php que queda fora da ruta onde apunta o sitio web, a orde para engadir un usuario. Lembrar que isto xa o vimos na UD3.
- Podemos empregar un procedemento almacenado de Mysql ou a orde SQL Insert. Lembrar que xa expliquei que é moito máis seguro empregar o procedemento ou ordes prepare.
Arquivo /var/www/confBD/bd.inc.php
1 define('INSERIR_USUARIOS',"INSERT INTO usuarios (login,password) VALUES ('%s','%s')");
- Creamos unha páxina php para dar de alta usuarios.
- Como queremos enviar a esta páxina información se o rexistro foi correcto ou se houbo algún tipo de erro, imos crear un include no que se amosarán o contido de dúas variables de sesión que imos empregar para isto:
Arquivo UD4_Exemplo1_Mensaxes.inc.php
<?php if (!empty($_SESSION['msg'])){ printf("<div>INFORMACIÓN: <b>%s</b>",$_SESSION['msg']); } if (!empty($_SESSION['error'])){ printf("<div>ERROR: <b>%s</b>",$_SESSION['error']); } unset($_SESSION['msg']); unset($_SESSION['error']);
- Arquivo UD4_Exemplo1_Rexistro_Formulario.php
<?php session_start(); unset($_SESSION['autenticado']); $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); // Para evitar ataques csrf ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="es" xml:lang="es"> <head> <meta charset="utf-8" /> <title>Formulario</title> <style> .formularios{ width: 30%; margin: 0px auto; } .etiqueta{ float: left; width: 190px; } .botonesformularios{ width: 50%; margin: 30px auto; text-align: center; } </style> </head> <body> <form id="frmValidacion" class="formularios" method="post" action="procesar_UD4_Exemplo1_Rexistro_Usuarios.php"> <input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>"> <div> <div class='etiqueta'>Login:</div> <input type="text" required size="15" maxlength="15" name="txtLogin" /> </div> <div> <div class='etiqueta'>Password:</div> <input type="password" required size="15" maxlength="15" name="txtPassword" /> </div> <div class="botonesformularios"> <input type='submit' value="ENVIAR" name="btnRexistrar" /> <input type='reset' value="LIMPAR" name="btnLimpar" /> </div> </form> <?php include('UD4_Exemplo1_Mensaxes.inc.php') ?> </body> </html>
- Liña 2: Sempre debemos ter o session_start() ao comezo da páxina se imos traballar con variables de sesión.
- Liña 3: Dita variable de sesión estará explicada posteriormente. Adiantar que é a variable que imos utilizar para deixar visualizar ao usuario as páxinas protexidas (que requiran unha autenticación previa).
- Liña 47: Facemos o include das mensaxes de erro e aviso se se producen na páxina de procesar.
- Visualizamos isto:
- O seguinte será rexistrar o usuario/password na táboa usuarios.
- Para iso imos facer uso da función password_hash() que permite encriptar un texto cun cifrado e vai ser a password a gardar na táboa de usuarios.
- Para comprobar o usuario cando intente entrar empregaremos password_verify().
- Arquivo procesar_UD4_Exemplo1_Rexistro_Usuarios.php
<?php /* Lembrar quitar isto ao probar o scripts sen erros */ ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL); session_start(); if (!isset($_POST['btnRexistrar']) || ($_POST['csrf_token'] !== $_SESSION['csrf_token'])){ // Se non vimos de premer o botón de rexistro volvemos a login. O csrf_token para evitar ataques unset($_SESSION['csrf_token']); header("location:UD4_Exemplo1_Rexistro_Formulario.php"); exit(); } require ('/var/www/confBD/bd.inc.php'); try { $conex = new mysqli(SERVIDOR, USUARIO, PASSWORD,BD); $conex->set_charset('utf8mb4'); // Xestionamos a operacion do segundo formulario => Alta , Baixa ou Modificacion if ((strlen($_POST['txtLogin'])<4) || (strlen($_POST['txtPassword'])<4)){ $_SESSION['error'] = sprintf("A lonxitude do login e password non poden ter menos de 4 caracteres..."); } else { // Eliminamos caracteres non permitidos $login = filter_var($_POST['txtLogin'],FILTER_SANITIZE_FULL_SPECIAL_CHARS, FILTER_FLAG_NO_ENCODE_QUOTES); $password = password_hash($_POST['txtPassword'],PASSWORD_DEFAULT); // Escapamos as comillas simples e dobres $login = $conex->real_escape_string(strtoupper($login)); $ordeSQL=sprintf(INSERIR_USUARIOS,$login,$password); $conex->query($ordeSQL); $_SESSION['msg'] = sprintf("Usuario rexistrado correctamente."); } } // Pecha o try da parte superior da páxina. Lembrar que aos usuarios non se lle deben amosar os erros. Isto está posto a nivel informativo para os programadores catch (mysqli_sql_exception $e) { $_SESSION['error']=sprintf("Erro mysql: %s",htmlentities($e->getMessage())); // Lembra que getMessage non se debe enviar ao cliente. Posto por motivos de depuración } catch (Expcetion $e) { $_SESSION['error']=sprintf("Erro xeral: %s",htmlentities($e->getMessage())); // Lembra que getMessage non se debe enviar ao cliente. Posto por motivos de depuración } finally{ if(!empty($conex)){ $conex->close(); } } unset($_SESSION['csrf_token']); // Para evitar ataques csrf $url = sprintf("UD4_Exemplo1_Rexistro_Formulario.php"); header("Location:" . $url); ?>
- Liña 8: Fixarse que despois da orde 'header' hai un exit para que o script non continúe executándose. Isto é así xa que o header non se enviará ao cliente ata que non remate o script. Dependerá de nos como programadores se queremos 'facer' algo máis antes de redirixir a páxina do navegador do cliente.
- Liña 13: Sempre debemos ter o session_start() ao comezo da páxina se imos traballar con variables de sesión.
- Liña 28: Encriptamos o password.
Validando usuarios
- Liñas 15-18: En caso de coincidir o login/password (nunha situación real teríamos que facer unha consulta a unha base de datos) utilizamos unha variable de sesión de nome autenticado e damos un valor de 1. En caso contrario terá un valor de 0.
- Dita variable debemos usala en todas as páxinas onde sexa necesario que o usuario estea autenticado. Vexamos un exemplo na seguinte páxina.
- Nome da páxina: UD4_Exemplo1_Validado.php
1 <?php 2 session_start(); 3 4 if ($_SESSION['autenticado']!=1) { // Mellor preguntar polo valor que permito o acceso. 5 header('location:UD4_Exemplo1_Validacion_Formulario.php'); 6 exit(); 7 } 8 9 ?> 10 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 11 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 12 <html xmlns="http://www.w3.org/1999/xhtml" lang="es" xml:lang="es"> 13 <head> 14 <title>Usuario autenticado</title> 15 </head> 16 <body> 17 <h1>Se podes ver isto es un usario autenticado...</h1> 18 19 <a href="UD4_Exemplo1_Validacion_Formulario.php">Pulsa para volver a validarte...</a> 20 </body> 21 </html>
- Liña 2: Sempre debemos ter o session_start() ao comezo da páxina se imos traballar con variables de sesión.
- Liñas 4-7: É onde facemos a validación do usuario. Se dito usuario non foi autenticado, entón irá a páxina inicial.
-- Ángel D. Fernández González -- (2023).