Linux: Dar de alta un nuevo usuario sin el comando adduser

El objetivo de esta entrada de blog es para ilustrar como se puede dar de alta a un nuevo usuario en Linux sin usar el comando adduser. En realidad esta fue una practica que hicimos en una clase de la escuela para la materia de Administracion de redes y se me hizo interesante republicarla (ya que ya la tenia en otro blog) para no perderla y bueno creo que el titulo lo dice todo. Primero que todo quiero mostrar las caracteristicas de la maquina donde se realiza la practica:

  • Distribucion linux                  Fedora 14
  • Versión del kernel                 2.6.35.11-83
  • Arquitectura del equipo        x86

Como se puede observar la prueba la he realizado en Fedora a la fecha que escribo esta era la mas reciente y está recién bajada e instalada de la página oficial.

Resumen de los pasos a realizar

  1. Dar de alta al usuario en el archivo /etc/passwd.
  2. Crear un grupo para el nuevo usuario en el archivo /etc/group
  3. Crear la carpeta hogar del nuevo usuario.
  4. Copiar los archivos ubicados en /etc/skel/ en la carpeta hogar del usuario.
  5. Establecer como propietario de su carpeta hogar al nuevo usuario.
  6. Cambiar de grupo a la carpeta hogar al grupo del nuevo usuario.
  7. Cambiar los permisos apropiados de la carpeta hogar del usuario.
  8. Asignar un password al nuevo usuario.
  9. Opcional; iniciar sesion para probar el nuevo usuario.

El paso 3 opcionalmente se puede realizar primero que todos si así se desea. Los pasos que siguen a continuación son estos mismos pasos pero detallados y por último se muestra una imagen de todos los pasos (no se muestran los archivos abiertos):

Paso 1: Dar de alta al usuario en el archivo /etc/passwd.

Antes de editar este archivo debemos tener privilegios de super usuario root, para adquirir estos privilegios, abrimos una consola y escribimos lo siguiente (solo lo que esta en color verde) y presionamos ENTER:

[adminredes@gnz ~]$  su
Contraseña:  {teclea aqui el password de root}
 
 

Despues de que tecleas el password y presionas nuevamente ENTER, si el password es correcto te haz convertido en el super usuario root.
 
Bueno, ahora vamos a abrir el archivo /etc/passwd con el editor nano, en la terminal escribe:

[root@gnz adminredes]#  nano /etc/passwd
 
 

A continuación se abrira dicho archivo, desplazate hasta abajo (con las flechas de cursor) despues de la ultima linea y escribe los siguiente:

xavier:x:502:502:Xavier Silva:/home/xavier:/bin/bash
 
 

Observa como he marcado los dos puntos con color rojo para que se te haga mas facil diferenciar los datos, tu archivo se debe parecer al de la siguiente imagen:
Pantallazo editando archivo /etc/passwd

El significado de los campos que conforman la ultima linea es:

  • xavier   Es el nombre del nuevo usuario que estas dando de alta.
  • x         Aqui iria el password pero como es una x, significa que el password esta encriptado (modo sombra) en el archivo /etc/shadow.
  • 502     Es el ID del nuevo usuario que estas creando (UID), como vez e puesto un ID+1 del ultimo que habia (501) y si quisieras dar de alta otro le corresponderia el que sigue, es decir el UID 503.
  • 502     Es el ID del grupo al que va a pertenecer este nuevo usuario. Aplica lo mismo que con el ID de usuario (…el que le sigue es el 503).
  • Xavier Silva   Es el  nombre real del nuevo usuario, si quisieras poner su telefono lo separas con una coma, si quieres poner su direccion con otra coma y asi sucesivamente. Es decir, este campo puede tener varios datos separados con coma. Este A este este campo a veces se le llama GECOS (General Electric Comprehensive Operating System, Sistema Operativo de General Electric).
  • /home/xavier   Es el directorio hogar de este usuario.
  • /bin/bash  Es la shell predeterminada que se le asigna a este usuario.

Ahora vamos a guardar los cambios realizados a este archivo que hemos abierto con el editor nano; presiona CTRL+O (o, no cero), y cuando te pida el nombre del archivo le das ENTER. A continuación cerramos el archivo; presiona CTRL+X. Hasta aqui ya hemos realizado el primer paso (ya no nos podemos detener o quedaria inconsistente la configuración del sistema, jajaja, tranquilo/a no te asustes).

Paso 2: Crear un grupo para el nuevo usuario en el archivo /etc/group.

Igual que en el paso 1 debes tener privilegios de root para editar este archivo, yo voi a dar por hecho que ya te has logueado como el super usuario root.

Procedamos a abrir el archivo /etc/group con el editor nano, en la terminal escribe (lo de verde):

[root@gnz adminredes]#  nano /etc/group
 
 

Con esto se abrira dicho archivo, desplazate hasta abajo (con las flechas de cursor) despues de la ultima linea y escribe lo siguiente:

xavier:x:502:
 
 

Observa que otra vez; he marcado los dos puntos con color rojo para que se te haga mas facil diferenciar los datos, tu archivo se debe parecer al de la siguiente imagen:

Archivo /etc/group
El significado de los campos que conforman esta linea es esta:

  • xavier   Es el nombre del nuevo grupo; estamos creando un nuevo grupo para el nuevo usuario que estas dando de alta.
  • x         Aqui iria el password del grupo, si hubiera un password este permitiria que nuevos usuarios se unieran al mismo.
  • 502     Es el ID del nuevo grupo que estas creando (GID), como vez e puesto un ID+1 del ultimo que habia (501) y si quisieras dar de alta otro le corresponderia el que sigue, es decir el GID 503.
  • Despues de los dos puntos (xavier:x:502:aqui!!) irian los miembros que pertenecen a este grupo, por ejemplo xavier:x:502:pepito,daniel,gonzasilve

Ahora guarda los cambios realizados a este archivo; presiona CTRL+O , y cuando te pida el nombre del archivo le das ENTER. A continuación cerramos el archivo; presiona CTRL+X.

Hasta aquí ya hemos realizado el segundo paso, vamos por el tercero…

Paso 3: Crear la carpeta hogar del nuevo usuario.

Que paso tan mas dificil (jejej), suponiendo que te has logueado como root, en la terminal teclea (lo de verde):

[root@gnz adminredes]#  mkdir /home/xavier
 
 

Listo.

Paso 4: Copiar todos los archivos ubicados en /etc/skel/ en la carpeta hogar del usuario.

Bien, primero vamos a entrar a la carpeta /etc/skel, suponiendo que eres root, en la terminal teclea (lo de verde):

[root@gnz adminredes]#  cd /etc/skel
 
 

Ahora vamos a ver (listar) que hay en esta carpeta, teclea:

[root@gnz skel]#  ls -la
 
 

Supongo que sabes para que sirve el comando ls, y sino pues aqui te lo vas a saber: Sirve para mostrar el contenido de un directorio, la l sirve para indicar que los muestre en forma tabular (modo detallado) y la a sirve para que muestre TODOS los archivos, incluso los ocultos.

Bueno, en mi caso el comando anterior me muestra lo siguiente (la linea en gris es el comando anterior):

[root@gnz skel]# ls -la
drwxr-xr-x.   4 root root  4096 feb 10 21:05 .
drwxr-xr-x.  126 root root 12288 mar 12 07:07 ..
-rw-r–r–.      1 root root    18 jun 22  2012 .bash_logout
-rw-r–r–.      1 root root   176 jun 22  2012 .bash_profile
-rw-r–r–.      1 root root   124 jun 22  2012 .bashrc
drwxr-xr-x.   2 root root  4096 sep 28 23:15 .gnome2
drwxr-xr-x.   4 root root  4096 feb 10 20:54 .mozilla

 
Como se puede ver ahi 3 archivos: (.bash_logout, .bash_profile y .bashrc) y dos carpetas (.gnome2 y .mozilla), ahi que copiarlos todos con los siguientes comandos, primero los archivos, en la terminal teclea (lo de verde):

[root@gnz skel]#  cp .bash_logout /home/xavier (pulsa ENTER)
[root@gnz skel]#  cp .bash_profile /home/xavier (pulsa ENTER)
[root@gnz skel]#  cp .bashrc /home/xavier (pulsa ENTER)
 
 

 
Ahora las carpetas…

[root@gnz skel]#  cp -R .gnome /home/xavier (pulsa ENTER)
[root@gnz skel]#  cp -R .mozilla /home/xavier (pulsa ENTER)
 
 

 
A las carpetas les agregue una R por que son carpetas (valga la redundancia) y éstas se deben copiar en forma Recursiva, para copiar todo lo que hay dentro.
 
Con esto hemos terminado de realizar el 4to paso, siguiente paso…

Paso 5: Establecer como propietario de su carpeta hogar al nuevo usuario.

Una vez copiados todos los archivos, ahora vamos a indicar que la carpeta /home/xavier pertenece al usuario xavier. Para hacer esto, en la terminal teclea (lo de verde):

[root@gnz skel]#  chown xavier -R /home/xavier
 
 

 
El comando chown permite cambiar de propietario a un archivo o carpeta. Igual que en el paso anterior agregue la R como parámetro para que también cambie de propietario a los archivos que copiamos en el paso 4. Continuemos…

Paso 6: Cambiar de grupo a la carpeta hogar, al grupo del nuevo usuario.

Casi terminamos, ahora vamos a indicar que la carpeta /home/xavier pertenece al grupo xavier (recuerda que este grupo lo dimos de alta en el archivo /etc/group), es decir, al grupo del nuevo usuario. Para hacer esto, en la terminal teclea (lo de verde):

[root@gnz skel]#   chgrp xavier -R /home/xavier
 
 

 
El comando chgrp tiene la misma sintaxis que chown y permite cambiar de grupo a un archivo o carpeta. Igual que en el paso anterior agregue la R como parámetro para que también cambie de grupo a los archivos que copiamos en el paso 4. Sigamos con el paso 7…

Paso 7: Cambiar los permisos apropiados de la carpeta hogar del usuario.

Ahora vamos a cambiar los permisos a todo el contenido de la carpeta hogar del usuario. Ummm, para entender esto te doy una breve explicación de los permisos en Unix

En Unix los permisos se pueden asignar de muchas maneras pero la que mas me gusta en lo personal es esta (por medio de números):
4 significa permiso de lectura
2 significa permiso de escritura
1 significa permiso de ejecucion

Estos números se pueden sumar para asignar una configuración de permisos mas adecuada, Ejemplos:
4+1=5, entonces el 5 significa lectura+ ejecución, otra configuración es 4+2+1=7, entonces el 7 significa que el archivo tiene permisos de lectura+escritura+ ejecución (todos los permisos), una ultima configuración; 4+2=6, entonces el 6 significa permisos de lectura+escritura.

El comando chmod permite asignar (o cambiar como quieras decirle) permisos a un archivo o carpeta. Ademas con el comando chmod se pueden asignar 3 diferentes tipos de permisos; los del propietario, los del grupo y los permisos para otros (que no son el propietario, ni los miembros del grupo), como se muestra en la siguiente imagen:
Los permisos en Unix

Como dije anteriormente el comando chmod tiene varias sintaxis y también se pueden asignar permisos a un grupo en particular por ejemplo: chmod ug+rwx setup.deb , esta asignando permisos de lectura(r), escritura(w) y ejecucion(x) al usuario(u) y al grupo(g) al que pertenece el archivo setup.deb. No entro en mas detalles para no confundirte.

Por lo regular, la configuración de permisos 755 es aceptable para cualquier archivo o carpeta. Así que esa configuración le aplicaremos, en la terminal teclea (lo de verde):

[root@gnz skel]#   chmod 755 -R /home/xavier
 
 

 
Siguiente paso…

Paso 8: Asignar un password al nuevo usuario.

En este ultimo paso vamos a asignarle un password al nuevo usuario, por que en este momento no tiene ninguno y por lo tanto no se podría iniciar sesión en el sistema. Suponiendo que sigues siendo root, en la terminal teclea (lo de verde):

[root@gnz skel]#   passwd xavier
Cambiando la contraseña del usuario xavier.
Nueva contraseña: (aqui teclea la contraseña y pulsa ENTER)
Vuelva a escribir la nueva contraseña: (otra vez, aqui teclea la contraseña y pulsa ENTER)
passwd: todos los tokens de autenticación se actualizaron exitosamente.
 
 

 
Como puedes darte cuenta despues de escribir el comando passwd xavier, el sistema nos pide el nuevo password, escribelo y pulsa ENTER, te lo vuelve a pedir, escribelo otra vez y pulsa ENTER.

…y waooo, con esto hemos terminado!¡!. En horabuena, con este paso hemos terminado de crear al nuevo usuario sin necesidad de usar el comando adduser de Linux.
 
Si eres de los excepticos…

Paso 9: [Opcional], Iniciar sesión para probar el nuevo usuario.

Por ultimo para probar que hemos creado al usuario correctamente no hay como iniciar una sesion en el sistema, para hacer esto, los puedes hacer de dos formas, Forma 1: suponiendo que sigues siendo root, en la terminal escribe (lo de verde):

[root@gnz skel]#   su – xavier
[xavier@gnz ~]$ (haz iniciado sesion con el nuevo usuario)
 
 

 
A continuación te muestro una imagen de todos los pasos realizados, (la edición del archivo passwd y group ya lo mostre arriba, en el paso correspondiente):
Comandos para crear usuario sin adduser

Forma 2: La otra forma es cerrar la sesión actual (si estas usando Linux) e iniciar como lo harías normalmente en Gnome (desde el GDM), ademas, al iniciar sesión de esta forma se van a crear automáticamente las carpetas Documentos, Imágenes, Vídeos… etc.

Aprovecho para mandar saludos a mi bola de amigos de ingeniería de sistemas del I.T. Zacatepec, Morelos.
 
Hasta pronto y espero te sirva de algo esta cosa… sugerencias y comentarios constructivos son bienvenidos. Y recuerda que en el mundo del bloggin comentar=agradecer.
 
 
 
Tux camina Tux maroma

Autenticacion de usuarios en PHP y MySql

Hola, mi cuenta de gmail ha sido vulnerada, por lo que las imágenes no se ven, pero esta entrada ya la he replicado en http://www.notas-programacion.com/2014/10/autenticacion-de-usuarios-en-php-y-mysql/, el contenido de este blog se estará migrando progresivamente allá, disculpa las molestias.

Como he visto que es muy solicitado el codigo que publique sobre como autenticar usuarios en java y MySql, decidi publicar esta nueva entrada que esta muy relacionada con dicho tema, pero ahora en PHP y un poquito mas completo; encriptacion del password en MD5.

Como decía anteriormente, en algunos sistemas a veces un requerimiento es que se manejen privilegios y por lo tanto usuarios, esto con el fin de controlar lo que cada usuario puede hacer/ver una vez dentro del sistema. En esta entrada únicamente se muestra como autenticar a los usuarios para entrar al sistema, es decir, cada usuario tendrá los mismos privilegios; aunque la tabla de usuarios de MySql (que mostrare mas adelante) ya incluye un campo que determina el tipo de usuario este campo no sera utilizado por ahora. Sin mas preámbulos muestro el ejemplo…

La base de datos

Como siempre que voi a hacer uso de una BD, empezare mostrando el script para recrear las tablas que usare en el ejemplo:

/* Crear la base de datos */
create database prueba;

/*Crear Catalogo de tipos de usuario */
create table ctg_tiposusuario
(
id_TipoUsuario	int not null auto_increment,
tx_TipoUsuario	varchar(100),
primary key(id_TipoUsuario)
);


/* Catalogo de usuarios */
create table tbl_users(
id_usuario int not null auto_increment,
tx_nombre varchar(50) not null,
tx_apellidoPaterno varchar(50),
tx_apellidoMaterno varchar(50),
tx_correo varchar(100),
tx_username varchar(50),
tx_password varchar(250),
id_TipoUsuario int,
dt_registro datetime,
primary key(id_usuario),
foreign key(id_TipoUsuario) references ctg_TiposUsuario(id_TipoUsuario)
);

/*Insertar tipos de usuarios de prueba*/
INSERT INTO `ctg_tiposusuario`( `tx_TipoUsuario`) VALUES ('Administrador');
INSERT INTO `ctg_tiposusuario`( `tx_TipoUsuario`) VALUES ('Usuario Normal');

/*passwrd: 12345*/
/*Insertar usuario de prueba*/
INSERT INTO tbl_users (tx_Nombre,tx_apellidoPaterno,tx_apellidoMaterno,tx_correo,
tx_username,tx_password,id_TipoUsuario,dt_registro) 
VALUES('Gonzalo','Silverio','Silverio','gonzasilve@gmail.com',
'gonzasilve','827ccb0eea8a706c4c34a16891f84e7b',1,'2012-11-09 17:35:40');

La base de datos que usare se llama prueba. Como se observa unicamente son dos tablas, ademas, he creado un catalogo con los diferentes tipos de usuario que pudiera haber, solo he añadido dos tipos de usuario (Administrador y Usuario normal) a modo de ejemplo, pero se pueden añadir mas. Si observas, inserto un usuario de prueba. Si quieres asignar otro password al usuario de prueba puedes utilizar esta sencilla herramienta que te permite generar un MD5 a partir de una cadena cualquiera: http://shalo.site50.net/obtener_md5.php

Herramientas necesarias

Supongo que para el momento de estar leyendo este articulo ya tienes el software necesario (ho al menos piensas instalarlo). Como he visto que los visitantes muchas veces son estudiantes de carrera ho aficionados a la programacion; pero con poca experiencia (me incluyo), voi a listar las herramientas de sw necesarias que debes tener yá en tu maquina si quieres probar este exquisito codigo :), puedes usar otro servidor y otro dbms, pero yo use estas:
Como ves son pocos requisitos, si no tienes alguno este es el momento para que lo instales. El servidor de correo de hecho es opcional, solo lo instale para hacer pruebas en mi computadora local (una laptop), si tienes dudas sobre hMailServer en la misma pagina viene mucha documentación acerca de como instalarlo y configurarlo. Si tienes más dudas puedes preguntarle al oraculo (google) escribiendo esto ‘hmailserver y php’.

Bueno vamos a lo interesante…

El código fuente

index.php

Este archivo permite mostrar la ventana de Login, en esta como es de suponerse el usuario introduce su nombre de usuario, su password y le da click al boton enviar, bueno muestro el codigo:
<!--     
	Instituto Tecnologico de Zacatepec, Morelos 
Descripcion:   Archivo para mostrar una pantalla de login con los campos;
				de usuario y password, los 2 datos se envian al archivo validarUsuario.php 
				por el metodo POST. 
Author:     Gonzalo Silverio  gonzasilve@gmail.com 
Archivo:    index.php 
-->

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>.:: Login ::. Ejemplo autenticar usuarios</title>
	
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<link rel="stylesheet" href="estilos.css" type="text/css">
	<script src="jquery171.js" type="text/javascript"></script> 
	<script src="jquery.validate.js" type="text/javascript"></script>
	<script type="text/javascript" src="jquery.alerts.js"></script>
	<link href="jquery.alerts.css" rel="stylesheet" type="text/css" />
	
	<script type="text/javascript">
	<!--
		$().ready(function() {
			$("#frmlogin").validate();
			$("#usuario").focus();
		});
	// -->
	</script>
	
</head>
<body>
<br /><br />
<form id="frmlogin" name="frmlogin"  method="POST" action="validarUsuario.php">
<table align="center" width="200px">
<tr>
	<td colspan="2" align="center"><h3>Iniciar sesi&oacute;n</h3></td>
</tr>
<tr>
	<td>Usuario</td>
	<td>
		<input type="text" name="usuario" id="usuario" class="required" maxlength="50">
	</td>
</tr>

<tr>
	<td>Password</td>
	<td>
		<input type="password" name="password" id="password" class="required"  maxlength="50">
	</td>
</tr>
<tr >
	<td colspan="2" >
		<a href="recuperarPassword.php">
			Olvide mi contrase&ntilde;a
		</a>
	</td>
</tr>

<tr>
	<td colspan="2" align="right">
		<input type="submit" name="enviar" value="Enviar" >
	</td>

</tr>
	
<tr>
	<td colspan="2" align="right" >
		<br/><a href="registro.php">Deseo registrarme</a>
	</td>
</tr>	
	<?php
	
	//Mostrar errores de validacion de usuario, en caso de que lleguen
	
		if( isset( $_POST['msg_error'] ) )
		{
			switch( $_POST['msg_error'] )
			{
				case 1:
			?>
			<script type="text/javascript"> 
				jAlert("El usuario o password son incorrectos.", "Seguridad");
				$("#password").focus();
			</script>
			<?php
				break;			
				case 2:
			?>
			<script type="text/javascript"> 
				jAlert("La seccion a la que intentaste entrar esta restringida.\n Solo permitida para usuarios registrados.", "Seguridad");
			</script>
			<?php		
				break;
			}		//Fin switch
		}

		//Mostrar mensajes del estado del registro
		
		if( isset( $_POST['status_registro'] ) )
		{
			switch( $_POST['status_registro'] )
			{
				case 1:
				if( $_POST['i_EmailEnviado'] ==1) {
				?>
					<script type="text/javascript"> 
						jAlert("Gracias, ha sido registrado exitosamente.\n Se le ha enviado un correo electronico de bienvenida, \npor favor, NO LO CONTESTE pues solo es informativo.", 'Registro');
					</script>
					<?php
				} else {
					?>
					<script type="text/javascript"> 
						jAlert("Gracias, ha sido registrado exitosamente.\n No se le ha podido enviar correo electronico de bienvenida, \nsin embargo, ya puede utilizar sus datos de acceso para iniciar sesion..", 'Registro');
					</script>
				<?php
				}

					break;			
				
				default:
			?>
				<script type="text/javascript"> 
					jAlert("Temporalmente NO se ha podido registrar, intente de nuevo mas tarde.", "Registro");
				</script>
			<?php		
			}		//Fin switch
		}
	?>
	
</table>
</form>
</body>
</html>

Como se puede ver para mostrar los mensajes de error utilizo la libreria JQuery, ya que me parecio que usar un alert() de javascript es algo feito, jajajaj. Como se ve el archivo en si solamente crea un formulario en el cual se dibujan dos cajas de texto; una para el usuario y otra para el password, un link para ir a la pantalla de recuperacion del password en caso de que al usuario se le haya olvidado y por ultimo se crea un boton tipo submit para enviar la informacion. Para validar campos vacios tambien utilizo JQuery. Ademas se puede ver que envio los dos datos de las cajitas a un archivo llamado validarUsuario.php por el metodo POST; el cual se encargara de accesar a la BD y verificar que los datos sean correctos.

Otra cosa interesante que se puede observar es que este archivo verifica si le llega un parametro llamado msg_error (con la funcion isset() de php) y en base a ese parametro (en realidad es un codigo de error) muestra un mensaje de error. A continuacion muestro un pantallazo como se ve el formulario en el navegador Chrome:

Pantalla de Login
En caso de que el usuario introduzca un nombre de usuario incorrecto se mostrara esta pantalla:
Pantalla Login, error usuario

Como se observa se ven mas atractivas las alertas con JQuery y ademas es sumamente facil utilizarlas.

validarUsuario.php

Este archivo es el que se encarga de recibir los datos del archivo index.php y los compara contra los que estan en la BD. Si el usuario y el password son correctos (existen en la BD) guarda el id del usuario en un formulario (el dato se envia oculto, hidden), inicializa una sesion , guarda algunas variables en dicha sesión y redirecciona hacia el archivo principal.php el cual es la pagina web que se supone debe mostrarse para usuarios registrados. En caso de que el usuario y/o password sean incorrectos entonces este archivo guarda igualmente un codigo de error en un formulario y redirecciona a la pagina de login, es decir, al archivo index.php. A continuacion se muestra su codigo fuente:
<?php
	/*
		Instituto Tecnologico de Zacatepec, Morelos 
	Descripcion:   Archivo que recibe los valores de 2 campos;
			un usuario y un password, los 2 datos se buscan si estan en la
			base de datos y redicciona al login o la pagina principal. 
	Author:     Gonzalo Silverio  gonzasilve@gmail.com 
	Archivo:    validarUsuario.php 
	*/ 

	//conectar BD
	include("conectar_bd.php");  
	conectar_bd();
	
	$usr = $_POST['usuario'];
	$pw = $_POST['password'];
	//Obtengo la version encriptada del password
	$pw_enc = md5($pw);
	
	$sql = "SELECT id_usuario FROM tbl_users
			INNER JOIN ctg_tiposusuario
			ON tbl_users.id_TipoUsuario = ctg_tiposusuario.id_TipoUsuario
			WHERE tx_username = '".$usr."'
			AND tx_password = '".$pw_enc."'	";	
	$result		=mysql_query($sql,$conexio); 

	$uid = "";
	
	//Si existe al menos una fila
	if( $fila=mysql_fetch_array($result) )
	{		
		//Obtener el Id del usuario en la BD 		
		$uid = $fila['id_usuario'];
		//Iniciar una sesion de PHP
		session_start();
		//Crear una variable para indicar que se ha autenticado
		$_SESSION['autenticado']    = 'SI';
		//Crear una variable para guardar el ID del usuario para tenerlo siempre disponible
		$_SESSION['uid']       		= $uid;
		//CODIGO DE SESION
		
		//Crear un formulario para redireccionar al usuario y enviar oculto su Id 
?>
		<form name="formulario" method="post" action="principal.php">
			<input type="hidden" name="idUsr" value='<?php echo $uid ?>' />
		</form>
<?php
	}
	else {
		//En caso de que no exista una fila...
		//..Crear un formulario para redireccionar al usuario a la pagina de login 
		//enviandole un codigo de error
?>
		<form name="formulario" method="post" action="index.php">
			<input type="hidden" name="msg_error" value="1">
		</form>
<?php
	}
?>
					
<script type="text/javascript"> 
	//Redireccionar con el formulario creado
	document.formulario.submit();
</script>
Como se observa; la mayoria del codigo esta comentado por lo que me ahorrare volver a explicar: Lo que si quiero mencionar es que en la linea 40 he dejado un comentario (CODIGO DE SESION), en esa linea si usted quiere puede generar un identificador de sesion, debido a que el ID de sesion de PHP a veces se pierde; usted puede crear un ID mas seguro; por ejemplo con base a la fecha y hr actual. la funcion session_id () permite leer o asignar el ID de la sesion.

La funcion session_start() permite iniciar una sesion o continuar una ya iniciada. Es por eso que en todas las paginas web que requieran que el usuario este autenticado se llama a esta funcion de PHP, esto lo podras ver en los demas archivos que mostrare mas adelante.

En la linea 37 y 39 se observa que es muy facil crear una variable de sesion con ayuda del array global $_SESSION[], basta con agregar un nuevo item y asignarle un valor, asi de facil. Posteriormente se pueden utilizar en cualquier pagina php por ejemplo para mostrar el Id del usuario y su Status en el navegador:
	echo "Id del usuario:".$_SESSION['uid'];
	echo "Ha iniciado sesion:".$_SESSION['autenticado'];

Facil ¿No?. Continuemos…

En la linea 12 del archivo validarUsuario.php se inserta un archivo llamado conectar_bd.php el cual se encarga de conectar con el DBMS, este archivo es el que muestro a continuacion…

conectar_bd.php

<?php
/*     
	Instituto Tecnologico de Zacatepec, Morelos 
Descripcion:   Conecta con el Manejador de Base de Datos (DBMS) y deja disponible una variable global (conexio)
		para ser utilizada posteriormente. 
Author:     Gonzalo Silverio  gonzasilve@gmail.com 
Archivo:    conectar_bd.php 
*/

$conexio;
function conectar_bd()
{
	global $conexio;
	//Definir datos de conexion con el servidor MySQL
	$elUsr = "root";
	$elPw  = "12345";
	$elServer ="localhost";
	$laBd = "prueba";
	
	//Conectar
	$conexio = mysql_connect($elServer, $elUsr , $elPw) or die (mysql_error());
	
	//Seleccionar la BD a utilizar
	mysql_select_db($laBd, $conexio ) or die (mysql_error());
}	
?>
Como se observa primero se definen los datos de conexion en variables locales a la funcion conectar_bd(). y posteriormente estas variables se usan como parametros para llamar a la funcion mysql_connect(), la cual es la que hace la peticion al dbms para conectarse. la funcion mysql_connect() devuelve un link que representa la conexion establecida al dbms, con este link guardado en la variable $conexio se selecciona la BD a utilizar (linea 24).

principal.php

Este archivo es la pantalla que el usuario ve si se logueo correctamente, nada mas como ejemplo he creado una muy sencilla. Cuando el usuario accede a esta pagina web se supone que ya paso por la pantalla de login y sus datos fueron verificados en la BD. Pero por seguridad antes de mostrarla verifico que efectivamente este logueado a travez de las variables de sesion que fueron creadas en el archivo validarUsuario.php. A continuacion muestro el codigo fuente:
<?php
/*     
	Instituto Tecnologico de Zacatepec, Morelos 
Descripcion:   Pantalla inicial que se muestra al usuario una vez que ha sido logueado correctamente. 
Author:     Gonzalo Silverio  gonzasilve@gmail.com 
Archivo:    principal.php 
*/

//Inicializar una sesion de PHP
session_start();

//Validar que el usuario este logueado y exista un UID
if ( ! ($_SESSION['autenticado'] == 'SI' && isset($_SESSION['uid'])) )
{
	//En caso de que el usuario no este autenticado, crear un formulario y redireccionar a la 
	//pantalla de login, enviando un codigo de error
?>
		<form name="formulario" method="post" action="index.php">
			<input type="hidden" name="msg_error" value="2">
		</form>
		<script type="text/javascript"> 
			document.formulario.submit();
		</script>
<?php
}

	//Conectar BD
	include("conectar_bd.php");  
	conectar_bd();

	//Sacar datos del usuario que ha iniciado sesion
	$sql = "SELECT  tx_nombre,tx_apellidoPaterno,tx_TipoUsuario,id_usuario
			FROM tbl_users
			LEFT JOIN ctg_tiposusuario
			ON tbl_users.id_TipoUsuario = ctg_tiposusuario.id_TipoUsuario
			WHERE id_usuario = '".$_SESSION['uid']."'";			
	$result		=mysql_query($sql); 

	$nombreUsuario = "";

	//Formar el nombre completo del usuario
	if( $fila = mysql_fetch_array($result) )
		$nombreUsuario = $fila['tx_nombre']." ".$fila['tx_apellidoPaterno'];
	
//Cerrrar conexion a la BD
mysql_close($conexio);
?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>.:: Inicio ::. Ejemplo autenticar usuarios</title>
	<link rel="stylesheet" href="estilos.css" type="text/css">
</head>
<body topmargin="0" >
<table align="right" width="350px" border="0">
<tr>												<!-- Dar Bienvenida al usuario -->
	<td  width="100px" align="right">Bienvenido <b><?php echo $nombreUsuario ?></b></td>
	<td  width="15px" align="center">
		<!-- Proporcionar Link para cerrar sesion -->
		<a href="cerrarSesion.php">Cerrar sesi&oacute;n</a>	
	</td>
</tr>
</table>
<br /><br />
<h2 align="center">Pantalla Principal</h2>

		<!-- Contenido inicial del sitio web -->
		
<body>
</html>
Como decia en la lineas anteriores, cuando una pagina esta restringida lo primero que se debe hacer es verificar que el usuario esta logueado y tiene permisos para ver dicha pagina. Como dije que no mostraria como dar permisos a los usuarios, en este ejemplo solo se comprueba que haya una sesion iniciada y que exista entre las variables de sesion un UID (User Id); Id del usuario en la Base de datos.

Si se verifica que esas condiciones se cumplen entonces se obtienen los datos del usuario, tal como su nombre , correo electronico, etc. Yo solo saque su nombre completo y lo mostre en la esquina superior derecha para que el usuario tenga la sensacion (jajajajj “sienta”) que a entrado al portal. A continuacion muestro un pantallazo de este archivo en el navegador:

Pantalla de inicio del usuario logueado

Como se observa tambien se ha puesto al usuario un link para que cierre su sesion.

Seguridad

Imaginemos que un usuario malintencionado escribe directamente la URL de este archivo en su navegador (escribe http://localhost/autenticar_usuarios/principal.php) pensando que con esto puede entrar y ver el contenido del sitio. Perdera su tiempo pues para eso presisamente se hace la validacion al inicio y solamente vera un mensaje de error como el que se ve a continuacion:

Mensaje de error al entrar a pagina principal sin login

cerrarSesion.php

Este archivo es al que apunta el enlace “Cerrar sesión ” que esta a un lado del nombre de usuario (una vez que ha iniciado su sesión). Este archivo se encarga de destruir todas las variables de sesión y terminar la sesion; todo esto se hace con las funciones que PHP ya trae incluidas.
<?php
/*     
	Instituto Tecnologico de Zacatepec, Morelos 
Descripcion:   Archivo para destruir las variables de sesion de un usuario logueado y terminar la sesion,
				 	ademas redirecciona nuevamente a la pagina de login. 
Author:     Gonzalo Silverio  gonzasilve@gmail.com 
Archivo:    cerrarSesion.php 
*/

session_start();
// Destruye todas las variables de la sesion
session_unset();
// Finalmente, destruye la sesion
session_destroy();

//Redireccionar a la pagina de login
header ("Location: index.php");

?>
Como se ve es muy corto el archivo. No doy mas explicacion ya que cada instruccion esta comentada.

recuperarPassword.php

En la pagina de login, si observas hay un link que dice Olvide mi contraseña, este link nos manda al archivo recuperarPassword.php. Este archivo permite enviar un nuevo password al usuario, el usuario solo debe escribir su correo electronico y automaticamente se generara un nuevo password de nueve caracteres y se le enviara a dicho email. Obviamente que el correo proporcionado se valida que exista en la BD; Como se observa en la BD el password esta encriptado en MD5 por lo que es necesario proporcionarle otro; no hay forma descifrar el password anterior.
<?php
	/*
		Instituto Tecnologico de Zacatepec, Morelos 
	Descripcion:   Este archivo permite preguntar al usuario su correo electronico para enviarle un nuevo
						password. 
	Author:     Gonzalo Silverio  gonzasilve@gmail.com 
	Archivo:    recuperarPassword.php 
	*/ 
?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>.:: Recuperar Password ::. </title>
	
	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
	<link rel="stylesheet" href="estilos.css" type="text/css">
	<script src="jquery171.js" type="text/javascript"></script> 
	<script src="jquery.validate.js" type="text/javascript"></script>
	<script type="text/javascript" src="jquery.alerts.js"></script>
	<link href="jquery.alerts.css" rel="stylesheet" type="text/css" />
	
	<script type="text/javascript">
	<!--
		$().ready(function() {
		$("#recPassword").validate({
		rules: {
		/*A continuacion los nombres de los campos y sus reglas a cumplir */
			correo2: {
			required: true,
			email: true,
			equalTo: "#correo"
			},
			correo: {
			required: true,
			email: true
			}


		}
		});
		$("#correo").focus();
		});
	// -->
	</script>
	
</head>
<body>
<br /><br />


<form id="recPassword" name="recPassword"  method="POST" action="recuperarPassword.php">

<table align="center" width="400px">

<tr>
	<td colspan="2" align="center"><h3><b>Recuperar Password</b></h3></td>
</tr>

<?php
//Si llega el parametro correo y no viene vacio
if( isset( $_POST['correo'] ) && $_POST['correo'] != '' )
{
	//Conectar la BD
	include("conectar_bd.php");  
	conectar_bd();

	//Recuperar la direccion de email que llega
	$elcorreo   = $_POST['correo'];
	
	//Verificar si existe el correo en la BD
	$sql = "SELECT  id_usuario,tx_username,tx_nombre,tx_apellidoPaterno
			FROM tbl_users
			WHERE tx_correo = '".$elcorreo."'";			
	$rs_sql	= mysql_query($sql);

	//Si no existe el correo... 
	if ( !( $fila 	= mysql_fetch_object($rs_sql) )  )
	{
	//Mostrar msg de error al usuario (en esta misma pagina)
?>
	<input type="hidden" id="error" value="1">			
	<script type="text/javascript"> 
	location.href="recuperarPassword.php?error="+document.getElementById('error').value;
	</script>
<?php
	}
	
	//En caso de que si exista un email como el k llega, leer de la BD los datos del usuario
	$idusr 	= $fila->id_usuario;		//Servira para actualizar el pw
	$nombre = $fila->tx_nombre." ".$fila->tx_apellidoPaterno;
	$nick 	= $fila->tx_username;
	
	// Generacion de un nuevo Password
	$pasw = "";
	$abecedario = array("A","B","C","D","E","F","G","H","J","K","L","M","N","O","P","Q","R","S","T",
"U","V","W","a","b","c","d","e","f","g","h","j","k","l","m","n","o","p","q","r","s","t","u","v","w");
	$simbolos 	= array(",","}","{","-","|","!","#","$","%","&","/","(",")","=","?","¡",
"*","]","[","_",":",";","+");
	for($i=0;$i<3; $i++)
	{
		$md 	= rand(1,2);
		$pasw 	.=  (($md%2)==0) ? $abecedario[rand(0,43)] : rand(0,9);  
		$md 	= rand(1,2);
		$pasw 	.=  (($md%2)==0) ? rand(0,9) :  $simbolos[rand(0,23)];  
		$md 	= rand(1,2);
		$pasw 	.=  (($md%2)==0) ?   $simbolos[rand(0,23)] : $abecedario[rand(0,43)] ;		
	}		
	
	// Le  Envio  por correo electronico  su nuevo password 
     $seEnvio;			//Para determinar si se envio o no el correo
     $destinatario = $elcorreo;				//A quien se envia
     $nomAdmin 			= 'Gonzalo Silverio';		//Quien envia
	 $mailAdmin 		= 'gonzasilve@gmail.com';	//Mail de quien envia
	 $urlAccessLogin = 'http://localhost/autenticar_usuarios/';	//Url de la pantalla de login

     $elmensaje = "";     
     $asunto = "Nueva contraseña para ".$nick;

     $cuerpomsg ='
		<h3>.::Recuperar Password::.</h3>
		<p>A peticion de usted; se le ha asignado un nuevo password, utilice los siguientes datos para acceder al sistema</p>
		  <table border="0" >
			<tr>
			  <td colspan="2" align="center" ><br> Nuevos datos de acceso para <a href="'.$urlAccessLogin.'">'.$urlAccessLogin.'</a><br></td>
			</tr>
			<tr>
			  <td> Nombre </td>
			  <td> '.$nombre.' </td>
			</tr>
			<tr>
			  <td> Username </td>
			  <td> '.$nick.' </td>
			</tr>
			<tr>
			  <td> Password </td>
			  <td> '.$pasw.' </td>
			</tr>
		  </table> ';
		  
	date_default_timezone_set('America/Mexico_City');
		  
	//Establecer cabeceras para la funcion mail()
	//version MIME
	$cabeceras = "MIME-Version: 1.0\r\n";
	//Tipo de info
	$cabeceras .= "Content-type: text/html; charset=iso-8859-1\r\n";
	//direccion del remitente
	$cabeceras .= "From: ".$nomAdmin." <".$mailAdmin.">";
	$resEnvio = 0;
	//Si se envio el email
	if(mail($destinatario,$asunto,$cuerpomsg,$cabeceras))
	{
		//Actualizar el pwd en la BD
		$sql_updt = "UPDATE tbl_users SET tx_password = '".md5($pasw)."' 
		WHERE (id_usuario = ".$idusr.")
		AND (tx_correo = '".$elcorreo."')";
		$res_updt = mysql_query($sql_updt);
		$resEnvio = 1;
	}

	//Cerrrar conexion a la BD
	mysql_close($conexio);
		
	// Mostrar resultado de envio (en esta misma pagina)
	?>
		<input type="hidden" id="enviado" value="<?php echo $resEnvio ?>">
		<input type="hidden" id="elcorreo" value="<?php echo $elcorreo ?>">
		<script type="text/javascript">
			location.href="recuperarPassword.php?enviado="+document.getElementById('enviado').value+"&elcorreo="+document.getElementById('elcorreo').value;
		</script>
	<?php	
}
else
{
?>

<tr>
	<td colspan="2">Escriba su correo electronico con el que se ha registrado, 
		se le enviara un nuevo password a su correo electronico:<br /><br /> 
	</td>
</tr>

<tr>
	<td>Correo electronico:</td>
	<td>
		<input type="text" name="correo" id="correo"  maxlength="50" />
	</td>
</tr>
<tr>
	<td>Confirme Correo electronico:</td>
	<td>
		<input type="text" name="correo2" id="correo2" maxlength="50" />
	</td>
</tr>

<?php
	//Si llega un codigo de error
	if( isset($_GET['error']) && $_GET['error']==1 )
	{
		echo "<tr><td colspan='2'><br><font color='red'>El correo electronico no pertenece a ningun usuario registrado.</font><br></td></tr>";
	}
	else if( isset($_GET['enviado']) && isset($_GET['elcorreo'])  )
	{
		//Si se envio correctamente el nuevo password
		if( $_GET['enviado']==1 ) 
			echo "<tr><td colspan='2'><br><font color='green'>Su nueva contrase&ntilde;a ha sido enviada a <strong>".$_GET['elcorreo']."</strong>.</font><br></td></tr>";
		else if( $_GET['enviado']==0 ) 
			echo "<tr><td colspan='2'><br><font color='red'>Por el momento la nueva contrase&ntilde;a no pudo ser enviada a <strong>".$_GET['elcorreo']."</strong>.<br>
			Intente de nuevo mas tarde.</font></td></tr>";
	}
?>

<tr>
	<td align="center" colspan="2">
		<br /><br /> 
		<input type="button" onClick="javascript: location.href='index.php'" name="cancelar" value="Cancelar" >
		&nbsp;&nbsp;&nbsp;&nbsp;
		<input type="submit" name="enviar" value="Enviar" >
	</td>
</tr>

<?php
}
?>

</table>
</form>
</body>
</html>

Para mas seguridad el password nunca se muestra al usuario, por el contrario; se le asigna otro (formado aleatoriamente) y se le envia por correo electronico. Como se observa en la linea 60 se comienza comprobando si llega un parametro llamado ‘correo’; si llega esto quiere decir que el formulario de recuperacion de password ya fue enviado y el correo que esta llegando es de un usuario al que se le debe asignar un nuevo password. Por el contrario; sino llega, se dibujan dos cajas de texto para permitir al usuario escribir su correo electronico y se le pueda enviar su password.

Bueno, supongamos que a este archivo le llega un el parametro correo, entonces de la linea 62 a la linea 85 se comprueba si ese email existe en la BD. sino existe, entonces se redirecciona al usuario a este mismo archivo pero con un codigo de error, el cual servira para mostrar un texto al usuario avisando que su correo electronico no existe. En caso de que si exista el email en la BD (no se cumple la condicion de la linea 76) entonces se recuperan los datos del usuario (linea 88 a la 90) y posteriormente se le genera un nuevo password (linea 93 a la 104), observe la forma como he generado el nuevo password del usuario; cada ciclo agrega 3 caracteres: el primero puede ser una letra ho un numero, el segundo puede ser un numero o un simbolo del array con el mismo nombre, el tercero puede ser un simbolo o una letra (Como son tres ciclos entonces el password tendra nueve caracteres).

Y ya por ultimo se le envia el password a su correo electronico del usuario (linea 106 a la linea 165). Algo que me gustaria resaltar es que el nuevo password debe ser actualizado en la BD para que la proxima vez el usuario intente iniciar sesion pues este password sea valido, ademas, solo se debe de actualizar despues de notificar al usuario (envio de email correcto), tal como se hace en este ejemplo.

A continuacion pongo una imagen del error que aparece en caso de que el email escrito no exista:

El email no existe en la Base de datos

Mensaje en caso de que el email haya sido enviado correctamente:

Nuevo password asignado correctamente

Ya no pongo el mensaje del error en caso de que NO se envie el email (falle la funcion mail() de php), porque es muy obvia, pero, a continuación dejo una imagen del eMail que le llega al usuario, con sus nuevos datos de acceso:

Email con nuevo password del usuario

registro.php

A peticion de muchos de los visitantes que preguntan (ya sea en privado o en comentarios de esta entrada) como registrar usuarios en php decidi exponer un ejemplo. En la pantalla de Login si observas aparece un enlace (hipervinculo) con la leyenda Deseo registrarme; el codigo que muestro a continuacion es del archivo que se muestra en el navegador al dar click en dicho enlace. Este archivo, en resumen, muestra un formulario creado con HTML para que el usuario capture sus datos personales y datos de acceso (username y password) envie dichos datos al script guardarRegistro.php que guarda los datos en la base de datos. El codigo es este…
<?php
	/*
		Instituto Tecnologico de Zacatepec, Morelos
	Descripcion:   Este archivo muestra un formulario que permite al usuario
		capturar sus datos y personales y de acceso.
	Author:     Gonzalo Silverio  gonzasilve@gmail.com
	Archivo:    registro.php
	*/

$str_nombre 		= "";
$str_apPaterno 	= "";
$str_apMaterno 	= "";
$str_correo 		= "";
$str_username 	= "";
$str_password 	= "";
$str_password2 	= "";

if( isset($_POST['str_nombre']) ) 		
	$str_nombre 		= trim($_POST['str_nombre']);
if( isset($_POST['str_apPaterno']) ) 
	$str_apPaterno 	= trim($_POST['str_apPaterno']);
if( isset($_POST['str_apMaterno']) ) 
	$str_apMaterno 		= trim($_POST['str_apMaterno']);
if( isset($_POST['str_correo']) ) 
	$str_correo 	= trim($_POST['str_correo']);
if( isset($_POST['str_username']) ) 
	$str_username 	= trim($_POST['str_username']);
if( isset($_POST['str_password']) ) 
	$str_password 	= trim($_POST['str_password']);
if( isset($_POST['str_password2']) ) 
	$str_password2 	= trim($_POST['str_password2']);


?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>.:: Registrar Usuario ::. </title>

	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
	<link rel="stylesheet" href="estilos.css" type="text/css">
	<script src="jquery171.js" type="text/javascript"></script>
	<script src="jquery.validate.js" type="text/javascript"></script>
	<script type="text/javascript" src="jquery.alerts.js"></script>
	<link href="jquery.alerts.css" rel="stylesheet" type="text/css" />

	<script type="text/javascript">
	<!--
		$().ready(function() {
		$("#registrar_usuario").validate({
		rules: {
		/*A continuacion los nombres de los campos y sus reglas a cumplir */
			tx_nombre: {
				required: true,	minlength: 3
			},
			tx_apPaterno: {
				required: true, minlength: 3
			},
			tx_apMaterno: {
				required: true,	minlength: 3
			},
			tx_correo: {
				required: true,	minlength: 5, email: true
			},
			tx_username: {
				required: true,	minlength: 5
			},
			tx_password: {
				required: true,	minlength: 5
			},
			tx_password2: {
				required: true,	minlength: 5,	equalTo: "#tx_password"
			}

		},
		/*A continuacion los campos y los mensajes en caso de que no se cumplan las reglas */
		messages: {
			tx_nombre: {
				required: "Por favor, escriba su Nombre.",
				minlength: jQuery.format("Su Nombre como minimo debe tener {0} caracteres.")
			},
			tx_apPaterno: {
				required: "Por favor, escriba su Apellido Paterno.",
				minlength: jQuery.format("Su Apellido Paterno como minimo debe tener {0} caracteres.")
			},
			tx_apMaterno: {
				required: "Por favor, escriba su Apellido Materno.",
				minlength: jQuery.format("Su Apellido Materno como minimo debe tener {0} caracteres.")
			},
			tx_correo: {
				required: "Por favor, escriba una direccion de correo electronico valida.",
				minlength: jQuery.format("Por favor, escriba una direccion de correo electronico valida.")
			},
			tx_username: {
				required: "Por favor, escriba un nombre de usuario. Este dato le servira para iniciar sesion y ver el contenido.",
				minlength: jQuery.format("Su nombre de usuario como minimo debe tener {0} caracteres.")
			},
			tx_password: {
				required: "Por favor, escriba una contraseña.",
				minlength: jQuery.format("Su contraseña como minimo debe tener {0} caracteres.")
			},
			tx_password2: {
				required: "Por favor, repita la contraseña anterior.",
				minlength: jQuery.format("Su contraseña como minimo debe tener {0} caracteres."),
				equalTo: "Por favor, repita la contraseña anterior.",
			}

		}

		});
		$("#tx_nombre").focus();
		});
	// -->
	</script>

</head>
<body>
<br />


<form id="registrar_usuario" name="registrar_usuario"  method="POST" action="guardarRegistro.php">

<table align="center" width="600px">

<tr>
	<td colspan="2" align="center"><h3><b>Registrar usuario</b></h3></td>
</tr>

<tr>
	<td colspan="2">Gracias por tu interes en registrarte. Para hacerlo, solo debes llenar
	los siguientes campos y pulsar el boton <b>Registrarme</b>. Para hacer mas rapido el registro y
	asi tu puedas acceder al contenido, tu cuenta se activa inmediatamente.<br /><br />
	</td>
</tr>
	
	<?php
		//Si llega el parametro error y no viene vacio
		if( isset( $_POST['error'] ) && $_POST['error'] != '' ) {
	?>
		<tr>
			<td colspan="2" >
				<font color="red">
				<ul>
					<?php
						echo $_POST['msgs_error'];
					?>
				</ul>
				</font>
			</td>
		</tr>
	<?php
		}
	?>

	
	<tr>
		<td><label for="tx_nombre">Nombre(s)</label></td>
		<td>
			<input type="text" name="tx_nombre" id="tx_nombre" value='<?php echo $str_nombre ?>' size="30"  maxlength="30" />
		</td>
	</tr>
	<tr>
		<td><label for="tx_apPaterno">Apellido paterno</label></td>
		<td>
			<input type="text" name="tx_apPaterno" id="tx_apPaterno" value='<?php echo $str_apPaterno ?>' size="30"  maxlength="30" />
		</td>
	</tr>
	<tr>
		<td><label for="tx_apMaterno">Apellido materno</label></td>
		<td>
			<input type="text" name="tx_apMaterno" id="tx_apMaterno"  value='<?php echo $str_apMaterno ?>' size="30"  maxlength="30" />
		</td>
	</tr>
	<tr>
		<td><label for="tx_correo">Correo electronico</label></td>
		<td>
			<input type="text" name="tx_correo" id="tx_correo"  value='<?php echo $str_correo ?>' size="30"  maxlength="30" />
		</td>
	</tr>
	<tr>
		<td><label for="tx_username">Nombre de usuario</label></td>
		<td>
			<input type="text" name="tx_username" id="tx_username"  value='<?php echo $str_username ?>' size="25"  maxlength="25"  />
		</td>
	</tr>
	<tr>
		<td><label for="tx_password">Contrase&ntilde;a</label></td>
		<td>
			<input type="password" name="tx_password" id="tx_password"  value='<?php echo $str_password ?>'  size="25"  maxlength="25" />
		</td>
	</tr>
	<tr>
		<td><label for="tx_password2">Confirme la contrase&ntilde;a</label></td>
		<td>
			<input type="password" name="tx_password2" id="tx_password2"  value='<?php echo $str_password2 ?>'  size="25"  maxlength="25" />
		</td>
	</tr>
	<tr>
		<td>Tipo de usuario</td>
		<td>
			<input type="hidden" name="i_tipoUsuario" id="i_tipoUsuario" value="2"   />
			<input type="radio" name="rad_TipoUsuario" id="rad_TipoUsuario" disabled value="2" checked="checked"  /> Usuario normal &nbsp;&nbsp;&nbsp;
			<input type="radio" name="rad_TipoUsuario" id="rad_TipoUsuario" disabled value="1"  /> Administrador
		</td>
	</tr>

<tr>

	<td align="center" colspan="2">
		<br /><br />
		<input type="button" onClick="javascript: location.href='index.php'" name="cancelar" value="Cancelar" >
		&nbsp;&nbsp;&nbsp;&nbsp;
		<input type="submit" name="registrarme" value="Registrarme" >
	</td>
</tr>

</table>
</form>
</body>
</html>
Como puedes observar esta un poco extenso (como 200 lineas sin lineas en blanco); ese es el precio de validar de una manera rigurosa los datos que el usuario introduce en los cuadros de texto. Tratare de explicar un poco este archivo, pero antes te muestro una imagen de la pagina web que se genera a partir del codigo fuente anterior:

Pagina web para registrar usuarios

De la linea 10 a 16 se declaran y limpian variables, una para cada dato del usuario que se va a registrar, enseguida en la linea 18 se verifica si esta llegando (si exite, con isset()) la variable de str_nombre, si se cumple que si existe dicha variable; hay una variable con el mismo nombre que se declaro antes (linea 10), entonces se le asigna el valor que llega. Cuando llegan datos significa que ya se habian enviado los datos al archivo guardarRegistro.php y éste los esta regresando si no los pudo guardar. Esta operacion la realiza para cada dato del usuario.

Si continuamos viendo el codigo se observa que de la linea 50 a la 100 es codigo javascript donde ajustamos parametros del plugin de validacion de JQuery. A este tipo de validacion se le conoce como validacion del lado cliente, en este caso el cliente es el navegador.

En la linea 121 se observa que esta escrito el encabezado del formulario y en su parametro action estamos diciendole que envie los datos de dicho formulario al archivo guardarRegistro.php el cual se encargara de guardarlos en la base de datos (no sin antes validarlos en el lado servidor).

En la linea 138 estamos verificando si existe/llega una variable llamada error y en caso de que si, mostramos la lista de errores que ocurrieron al guardar. La lista de errores vienen en otra variables llamada msg_error. Observa como en la linea 143 y 147 se abre y cierra, respectivamente una lista desordenada de HTML, la variable msg_error trae los <li> </li> correspondientes, cada <li> es un error que ocurrio al intentar guardar en el archivo guardarRegistro.php. En caso de que hayan ocurrido errores se mostrara una pantalla similar a esta:

Horrores al registrar un usuario

guardarRegistro.php

Este archivo recibe los datos del archivo registro.php y los guarda en la base de datos. Antes de guardar realiza varias validaciones, mas abajo esta la explicacion pero, veamos el codigo…
<?php
	/*
		Instituto Tecnologico de Zacatepec, Morelos
	Descripcion:   Este archivo permite guardar un nuevo usuario.
	Author:     Gonzalo Silverio  gonzasilve@gmail.com
	Archivo:    guardarRegistro.php
	*/
	//Recuperar los datos del formulario de registro
	$str_nombre			=trim($_POST['tx_nombre']);
	$str_apPaterno	=trim($_POST['tx_apPaterno']);
	$str_apMaterno	=trim($_POST['tx_apMaterno']);
	$str_correo			=trim($_POST['tx_correo']);
	$str_username		=trim($_POST['tx_username']);
	$str_password		=trim($_POST['tx_password']);
	$str_password2	=trim($_POST['tx_password2']);
	$i_TipoUsuario	=trim($_POST['i_tipoUsuario']);

	//Devuelve true si la cadena que llega esta VACIA
	function estaEnBlanco($cadena) {
		if(strlen( trim($cadena) ) == 0 )
			return true;
		return false;
	}

	//Devuelve true si la longitud de la cadena (primer parametro)
	// que llega  es menor que el numero (segundo parametro)
	function validaTamanio($cadena,$longitud) {
		if(strlen( trim($cadena) ) < $longitud )
			return true;
		return false;
	}

	// devuelve true SI ha escrito, un email NO VALIDO
	function esCorreoInvalido($str_email) {
		if(!filter_var(trim($str_email), FILTER_SANITIZE_EMAIL))
			return true;
		return false;
	}

	// devuelve una cadena escapada de algunos caracteres que
	// pudieran servir para un ataque de sql injection
	function escaparQuery($cadena) {
		$str_KeywordsSQL 			= array("select ","insert ","delete ","update ","union ");
		$str_OperadoresSQL 		= array("like ","and ","or ","not ","<",">","<>","=","<");
		$str_DelimitadoresSQL = array(";","(",")","'");

		//Quitar palabras reservadas y operadores
		for($i=0; $i<count($str_KeywordsSQL); $i++) {
			$cadena = str_replace($str_KeywordsSQL[$i], "",strtolower($cadena) );
		}
		for($i=0; $i<count($str_OperadoresSQL); $i++) {
			$cadena = str_replace($str_OperadoresSQL[$i], "",strtolower($cadena) );
		}
		for($i=0; $i<count($str_DelimitadoresSQL); $i++) {
			$cadena = str_replace($str_DelimitadoresSQL[$i], "",strtolower($cadena) );
		}

		return $cadena;
	}


	$mensajesAll= "";

	//Mensajes para el nombre
	if( estaEnBlanco($str_nombre) )
		$mensajesAll = "<li>Por favor, escriba su Nombre.</li>";
	if( validaTamanio($str_nombre,3) )
		$mensajesAll .= "<li>Su Nombre como minimo debe tener 3 caracteres.</li>";
	//Mensajes para el Apellido Paterno
	if( estaEnBlanco($str_apPaterno) )
		$mensajesAll .= "<li>Por favor, escriba su Apellido Paterno.</li>";
	if( validaTamanio($str_apPaterno,3) )
		$mensajesAll .= "<li>Su Apellido Paterno como minimo debe tener 3 caracteres.</li>";
	//Mensajes para el Apellido Materno
	if( estaEnBlanco($str_apMaterno) )
		$mensajesAll .= "<li>Por favor, escriba su Apellido Materno.</li>";
	if( validaTamanio($str_apMaterno,3) )
		$mensajesAll .= "<li>Su Apellido Materno como minimo debe tener 3 caracteres.</li>";
	//Mensajes para el Correo electronico
	if( estaEnBlanco($str_correo) || validaTamanio($str_correo,5) || esCorreoInvalido($str_correo) )
		$mensajesAll .= "<li>Por favor, escriba una direccion de correo electronico valida.</li>";
	//Mensajes para el nombre de usuario
	if( estaEnBlanco($str_username) )
		$mensajesAll .= "<li>Por favor, escriba un nombre de usuario. Este dato le servira para iniciar sesion y ver el contenido.</li>";
	if( validaTamanio($str_username,5) )
		$mensajesAll .= "<li>Su nombre de usuario como minimo debe tener 5 caracteres.</li>";
	//Mensajes para el password
	if( estaEnBlanco($str_password) )
		$mensajesAll .= "<li>Por favor, escriba una contrase&ntilde;a.</li>";
	if( validaTamanio($str_password,5) )
		$mensajesAll .= "<li>Su contrase&ntilde;a como minimo debe tener 5 caracteres.</li>";
	//Mensajes para la confirmacion del password
	if( estaEnBlanco($str_password2) || validaTamanio($str_password2,5) )
		$mensajesAll .= "<li>Por favor, confirme la contrase&ntilde;a anterior.</li>";
	if( trim($str_password) != trim($str_password2) )
		$mensajesAll .= "<li>Por favor, repita la contrase&ntilde;a anterior.</li>";	
	//Mensajes para el tipo de usuario
	if( estaEnBlanco($i_TipoUsuario) )
		$mensajesAll .= "<li>Por favor, indique el tipo de usuaurio.</li>";

	$log = $mensajesAll."<br>";

	//Si se generaron mensajes de error al validar...
	if ( trim($mensajesAll) != "" )	{
		//..Redireccion a la pagina de registro para mostrar msg de error al usuario
		//Enviar los datos que habia escrito antes de enviar
	?>
	<form id="frm_error"   name="frm_error" method="post" action="registro.php">
		<input type="hidden" name="error" value="1" />
		<input type="hidden" name="msgs_error" value='<?php echo $mensajesAll ?>' />
		<input type="hidden" name="str_nombre" value='<?php echo $str_nombre ?>' />
		<input type="hidden" name="str_apPaterno" value='<?php echo $str_apPaterno ?>' />
		<input type="hidden" name="str_apMaterno" value='<?php echo $str_apMaterno ?>' />
		<input type="hidden" name="str_correo" value='<?php echo $str_correo ?>' />
		<input type="hidden" name="str_username" value='<?php echo $str_username ?>' />
		<input type="hidden" name="str_password" value='<?php echo $str_password ?>' />
		<input type="hidden" name="str_password2" value='<?php echo $str_password2 ?>' />
	</form>
	<script type="text/javascript">
		//Redireccionar con el formulario creado
		document.frm_error.submit();
	</script>
<?php
		exit;
	}
?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>.:: Registrar Usuario ::. </title>

	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<link rel="stylesheet" href="estilos.css" type="text/css">
	<script src="jquery171.js" type="text/javascript"></script>
	<script src="jquery.validate.js" type="text/javascript"></script>
	<script type="text/javascript" src="jquery.alerts.js"></script>
	<link href="jquery.alerts.css" rel="stylesheet" type="text/css" />

	<script type="text/javascript">
	<!--
		$().ready(function() {

		});
	// -->
	</script>

</head>
<body>

<?php
	$mensajesAll				= "";
	$username_duplicado = false;
	$email_duplicado 		= false;
	//Escapar las cadenas para avitar SQL Injection
	$str_username = escaparQuery($str_username);
	$str_correo 	= escaparQuery($str_correo);

	//Conectar la BD
	include("conectar_bd.php");
	conectar_bd();

	
	//Validar que el nombre de usuario no exista en la BD
	$sql = "SELECT  id_usuario	FROM tbl_users
	WHERE tx_username = '".trim($str_username)."';";
	$rs_sql	= mysql_query($sql);
	$log .=  $sql."<br>";
		
	//Si ya existe el usuario en la BD...
	if ( $fila 	= mysql_fetch_object($rs_sql) )	{
		$mensajesAll = "<li>El nombre de usuario <b>".$str_username."</b> ya fue registrado 
		por otra persona. Por favor, escriba otro.</li>";
		$username_duplicado = true;
	}

	//Validar que el email no exista en la BD
	$sql = "SELECT  id_usuario	FROM tbl_users
	WHERE tx_correo='".$str_correo."';";
	$rs_sql	= mysql_query($sql);
	$log .=  $sql."<br>";

	
	//Si ya existe el email en la BD...
	if ( $fila 	= mysql_fetch_object($rs_sql) )	{
		$mensajesAll = "<li>El correo electronico <b>".$str_correo."</b> ya fue registrado 
		por otra persona. Por favor, escriba otro.</li>";
		$email_duplicado 		= true;
	}
	//Si ambos datos ya estan en la Base de datos mostrar un solo msg
	if( $username_duplicado && $email_duplicado)
		$mensajesAll = "<li>Ambos, nombre de usuario <b>".$str_username."</b> 
		y correo electronico <b>".$str_correo."</b> ya fueron registrados por otra persona.
		Por favor, cambie esos datos.</li>";
	//..Redireccion a la pagina de registro para mostrar msg de error al usuario
	//Enviar los datos que habia escrito antes de enviar
	
	$log .=  $mensajesAll."<br>";

	
	if ( trim($mensajesAll) != "" )	{
		//..Redireccion a la pagina de registro para mostrar msg de error al usuario
		//Enviar los datos que habia escrito antes de enviar
		?>
		<form id="frm_error"   name="frm_error" method="post" action="registro.php">
			<input type="hidden" name="error" value="2" />
			<input type="hidden" name="msgs_error" value='<?php echo $mensajesAll ?>' />
			<input type="hidden" name="str_nombre" value='<?php echo $str_nombre ?>' />
			<input type="hidden" name="str_apPaterno" value='<?php echo $str_apPaterno ?>' />
			<input type="hidden" name="str_apMaterno" value='<?php echo $str_apMaterno ?>' />
			<input type="hidden" name="str_correo" value='<?php echo $str_correo ?>' />
			<input type="hidden" name="str_username" value='<?php echo $str_username ?>' />
			<input type="hidden" name="str_password" value='<?php echo $str_password ?>' />
			<input type="hidden" name="str_password2" value='<?php echo $str_password2 ?>' />
		</form>
		<script type="text/javascript">
			//Redireccionar con el formulario creado
			document.frm_error.submit();
		</script>
			<?php
		exit;
	}
	
	
	//..Si llega asta aqui es que todos los datos son validos, procedemos a darlo de alta en BD
	$str_elNombre 				= $str_nombre." ".$str_apPaterno;
	$str_elNombreCompleto = $str_nombre." ".$str_apPaterno." ".$str_apMaterno;

	
	//Formar el query para el insert del nuevo usuario
	$queryInsert="INSERT INTO tbl_users (
	tx_nombre,
	tx_apellidoPaterno,
	tx_apellidoMaterno,
	tx_correo,
	tx_username,
	tx_password,
	id_TipoUsuario,
	dt_registro	) 
	VALUES(
	'".$str_nombre."',
	'".$str_apPaterno."',
	'".$str_apMaterno."',
	'".$str_correo."',
	'".$str_username."',
	'".md5($str_password)."',
	".$i_TipoUsuario.",
'".date("Y-m-d H:i:s")."');";
	
	$log .=  $queryInsert."<br>";

	//echo $log;
	//exit;
	
	mysql_query($queryInsert);

	// Le  Envio  un correo electronico  de bienvenida
	$destinatario = $str_correo;					//A quien se envia
	$nomAdmin 			= 'Gonzalo Silverio';			//Quien envia
	$mailAdmin 		= 'gonzasilve@gmail.com';		//Mail de quien envia
	$urlAccessLogin = 'http://localhost/autenticar_usuarios';		//Url de la pantalla de login

	$elmensaje = "";
	$asunto = $str_elNombre.", Gracias por registrarte!";

	$cuerpomsg ='
	<h2>.::Registrar usuarios::.</h2>
	<p>Le damos la mas cordial bienvenida, desde ahora usted podra gozar de los beneficios de 
	haberse identificado y acceder a contenido exclusivo de esta comunidad.</p>
		<table border="0" >
		<tr>
			<td colspan="2" align="center" >Sus datos de acceso para <a href="'.$urlAccessLogin.'">'.$urlAccessLogin.'</a><br></td>
		</tr>
		<tr>
			<td> Nombre </td>
			<td> <b>'.$str_elNombreCompleto.'</b> </td>
		</tr>
		<tr>
			<td> Nombre de usuario </td>
			<td> <b>'.$str_username.'</b> </td>
		</tr>
		<tr>
			<td> Password </td>
			<td> <b>'.$str_password.'</b> </td>
		</tr>
		</table> <br/><br/>
	<p><b>Gracias por su preferencia, hasta pronto.</b></p> <br><br>';

	date_default_timezone_set('America/Mexico_City');

	//Establecer cabeceras para la funcion mail()
	//version MIME
	$cabeceras = "MIME-Version: 1.0\r\n";
	//Tipo de info
	$cabeceras .= "Content-type: text/html; charset=iso-8859-1\r\n";
	//direccion del remitente
	$cabeceras .= "From: ".$nomAdmin." <".$mailAdmin.">";
	$i_EmailEnviado = 0;
	
	//Si se envio el email
	if( mail($destinatario,$asunto,$cuerpomsg,$cabeceras) )	
		$i_EmailEnviado = 1;
	
	//Cerrrar conexion a la BD
	mysql_close($conexio);

	// Mostrar resultado del registro
	?>
	<form id="frm_registro_status"   name="frm_registro_status" method="post" action="index.php">
		<input type="hidden" name="status_registro" value="1" />
		<input type="hidden" name="i_EmailEnviado" value='<?php echo $i_EmailEnviado ?>' />
	</form>
	<script type="text/javascript">
		//Redireccionar con el formulario creado
		document.frm_registro_status.submit();
	</script>
</body>
</html>

Empezamos recogiendo en varibles locales a este archivo los datos que nos llegan del archivo registro.php, esto se hace de la linea 8 a l6. Despues definimos 4 funciones, las cuales mas adelante nos serviran para hacer validaciones con los datos que acabamos de recibir. Cada una tiene un breve explicación asi que me ahorrare volver a hacerlo.

De la linea 64 a 99 validamos que los datos que llegan no vengan vacios (en blanco), ademas para algunos campos como el username y password validamos su tamaño. Observa como para cada campo que pudiera venir vacio o no cumplir el tamaño se siguen revisando los demas pero se agrega un item <li> con la descripcion del error. En la linea 104 se revisa si la lista NO esta vacia, sino esta vacia entonces regresamos todos los datos al archivo registro.php, para que el usuario no tenga que volver a escribirlos y solo corrija los que tienen error, y ademas mandamos una variable llamada error y la lista de errores que ocurrieron (con su descripcion). Ademas de mandar los errores debemos detener la ejecucion de este archivo, esto se hace en la linea 124.

Supongamos que no hubo errores de campos en blanco ni tamaños, entonces no se cumplira la condicion de la linea 104, entonces, el interprete de PHP se saltara hasta la linea 126 y continuara su ejecucion…

Lo que haremos ahora sera validar que el nombre de usuario e email escrito no existan en la BD, si algunos de los dos ya fue registrado volveremos a direccionar la ejecucion al archivo registro.php para que escriba otro username/pasword. Esto se hace de la linea 151 a 231, el codigo esta comentado por lo tanto evitare redundar en la explicacion.

Tal y como dice la linea 224, si la ejecucion llega asta dicha linea es que todos los datos son validos (han pasado las validaciones), entonces procedemos a darlo de alta en la base de datos. Despues de formar la sentencia SQL (insert) de la linea 230 a 247, se ejecuta (linea 254) y con lo cual el usuario ha sido dado de alta. Observa como en varios puntos del script voi guardando un log de la ejecucion (errores, querys, etc) en una variable llamada $log puedes imprimirla y detener la ejecucion en cualquier momento para ver que pasa detras del telon, observa como lo hago yo en la linea 251 y 252.

Como un plus e puesto el codigo como se le pueden enviar sus datos de acceso en un email, si recuerdas ya vimos como enviar un email en PHP en otra entrada de blog. A continuación un pantallazo del email que le llega al usuario que se acaba de registrar:
Email con sus datos de acceso
 
 
Despues de enviarle el email con sus datos direccionamos al usuario al archivo index.php (recuerda que ahi dio click en el enlace Deseo registrarme) junto con una bandera; $status_registro si esta bandera llega con valor 1 significa que el registro fue exitoso. el archivo index.php ya esta preparado para revisar si le llega esta bandera (fijate en linea 99). Pantalla de aviso que ha sido registrado:

Aviso de registro exitoso

Por ultimo no hay que olvidarse de cerrar la conexion a la base de datos, esto lo hago en la linea 304 del archivo guardarRegistro.php.

Demo

Si deseas ver el ejemplo funcionando Da click aqui. usa estos datos para probar el ejemplo, Usuario: visitante_wp, Contraseña: 12345. Si te registras no olvides revisar el SPAM!.
 
 
Bueno, eso es todo. Como siempre, si quieres el codigo deja tu email y te lo envio a la brevedad.  Si te gusto el articulo ¿me regalas un like?. Saludos.

 
 
A %d blogueros les gusta esto: