Bienvenida y bienvenido a este tutorial en el que realizaremos un generador de contraseñas con una interfaz gráfica. En un inicio puede parecer mucha teoría, pero es esta misma la que permite trabajar con esta metodología de manera muy veloz y con efectividad (siempre y cuando se practique con estructuras similares).
No te deprimas sino entiendes toda la teoría, esta puede resultar confusa y pesada en un inicio. Sin embargo, si pones en práctica esta metodología y lees el código con paciencia, podrás trabajar ágilmente pudiendo implementar nuevas funcionalidades durante el desarrollo del mismo.
Al finalizar este tutorial tendrás un programa idéntico o hasta mejor al que se muestra en las siguientes capturas de pantalla y con la posibilidad de agregar nuevas características y modificar valores para personalizarlo:
Espero que con estas capturas de pantalla te motives para terminar este proyecto 😄. Además, al final del tutorial hay un apartado con ideas para complementar y mejorar el proyecto (todas realizadas en el proyecto actual). Sin embargo, no tengas miedo de explorar con las ideas que te surjan y no olvides compartirlo 📣.
Para el desarrollo del proyecto haremos uso del paradigma de la Programación Orientada a Objetos (POO) y el lenguaje de programación: Python.
Nota: El programa lo he desarrollado totalmente en inglés, pero la explicación en este tutorial está totalmente en español.
Nuestro proyecto tiene como fin:
Primero necesitaremos el archivo .ico para que sea el ícono de nuestro programa. En este caso utilizaremos el que puedes descargar desde este link haciendo click en el recuadro verde que dice ICO. El ícono será el siguiente:
Nuestra segunda descarga es opcional, dado que podremos seleccionar otra tipografía, sin embargo, dado que queremos visualizar una contraseña será bueno distringuir entre una i mayúscula (I) y una l minúscula (l).
Es por esta razón que para el desarrollo de nuestro proyecto utilizaremos Argentum Sans Regular, ya que se puede notar claramente esta diferencia tal y como se aprecia en la siguiente imagen:
Font Argentum Sans Regular: Puedes acceder a esta tipografía desde aquí. Al entrar, te desplazarás hasta ver la primera opción que dice Argentum Sans Regular y harás click en TTF y (una vez terminada la descarga) darás doble click en el archivo para abrirlo. A continuación, seleccionarás Instalar en la ventana emergente que salga.
Listo, es hora de comenzar con nuestro proyecto 🚀. Empezaremos por analizar como va a funcionar nuestro programa. Esta será una de las partes más largas, pero no te frustres. Si tienes dudas, estas quedarán claras al plasmarlo en el código.
Visto el problema de esta forma resulta agobiante y confuso, así que haremos lo que todo desarrollador de Software hace: dividir un problema grande en pequeños problemas.
Por lo tanto, podemos ver que podemos divir el problema en 2 apartados: generar la contraseña y realizar la interfaz gráfica. Asimismo, dentro de generar contraseña debemos considerar utilizar POO y hacerlo personalizable. Finalmente, dentro de POO tendremos que considerar: que sea Modular y que emplee encapsulamiento.
De esta forma, tenemos el siguiente diagrama:
Entonces, llegados a este punto tenemos que ver que archivos crear y como ordernarlos para nuestro proyecto. Para eso analizaremos:
Un primer archivo debe ser el que tenga una Clase con encapsulamiento del cual obtengamos los datos de las librería string la cual contiene diferentes listas con los caracteres que utilizaremos.
Para que sea personalizable, debemos tener otro archivo con las constantes que podamos modificar fácilmente sus valores sin romper el código.
Para mejorar la modularidad, tendremos un tercer archivo (con otra clase) que se encargará de utilizar el primer archivo creado para generar una contraseña con un parámetro (longitud que debe tener) de forma aleatoria con la librería random.
Siguiendo con la modularidad, tendremos un archivo que se encargue de comunicar a la Interfaz Gráfica con el tercer archivo creado. Este archivo se encargará de seleccionar la longitud que pasará como parámetro a este tercer archivo.
Finalmente, nuestro quinto y último archivo será la interfaz gráfica para la cual utilizaremos la librería Tkinter y tkk. Además, este archivo recibirá toda la interacción del usuario y se comunicará con el cuarto archivo para que este le retorne la contraseña y pueda mostrarla al usuario.
No te preocupes si no entendiste del todo esta lógica. Visualiza el siguiente gráfico que lo plasma de una manera más visual:
Tal y como se aprecia en el gráfico, se puede ver de manera más clara que empleamos el clásico Modelo-Vista-Controlador o Model-View-Controller (MVC).
Para dejar claro la lógica del programa, explicaré cada uno de los archivos y su función:
ARCHIVO | FUNCIÓN |
---|---|
VIEW | Contendrá la interfáz gráfica con la librería de Tkinter y Ttk. Envía la selección de que tan fuerte debe ser la contraseña del usuario al CONTROLLER para que este le retorne la contraseña con la longitud correspondiente. |
UTILITY | Solo contendrá las constantes que nos permitirán hacer personalizable nuestro programa. Por ejemplo: Que tan fuerte debe ser la contraseña y las longitudes establecias por nosotros. |
CONTROLLER | Recibe que tan fuerte debe ser la contraseña del usuario y gracias a UTILITY puede asignarle un valor de longitud. Se comunicará con MODEL para que este le genere la contraseña aleatoria con estos datos y pueda devolvérsela a VIEW. |
MODEL | Recibe la longitud de la contraseña de parte de CONTROLLER y, con ayuda de la librería Random, selecciona aleatoriamente caracteres de una lista de las mismas. Esta lista se la pide a ENTITY para que así pueda devolverle la contraseña a CONTROLLER. |
ENTITY | Tiene en su poder la lista de los caracteres protegidos (encapsulamiento) para que sean inalterables y nadie pueda ver qué caracteres se emplean. Esto se logra gracias a la librería String. ENTITY se encargará de darle la información de esta lista protegida a MODEL para que él genere la contraseña y pueda enviársela a CONTROLLER y este último se la retorne a VIEW. |
Si vuelves a apreciar el gráfico notarás que el recorrido, al pedir una contraseña, será el siguiente:
Nota: La librería Tkinter y Ttk no aparece con ningún color de flecha porque es lo primero que se visualiza de manera constante.
Ya con el diagrama en mente procederemos a crear una carpeta para almacenar los archivos de nuestro proyecto. Dentro de esta crearemos los 5 archivos mencionado anteriormente: entity.py, model.py, controller.py, utility.py y view.py. Finalmente, crearemos la carpeta “images” donde guardaremos el ícono que descargamos al inicio del proyecto (En este caso renombramos el nombre del archivo a “lock” para que sea fácil de acceder a él en el futuro).
Aplicando la abstracción, notaremos que la clase Password contendrá como atributos 3 listas de los caracteres válidos que usará nuestro generador de contraseña.
Para tener estas listas, importaremos de la librería string:
Sin embargo, tenemos que recordar que vamos a aplicar encapsulamiento lo cual hace que nuestros atributos sean inviolables e inalterables. Para esto utilizaremos el doble guión bajo (self.__nombreDelAtributo) para encapsularlo.
Tal y como se observa, en el código hemos incluido los métodos para acceder a estos datos encapsulados. Sólo hemos puesto los métodos para acceder a ellos porque no queremos que alguien los modifique. Esto equivale al método getter.
Ahora, antes de empezar con model, procederemos a llenar el archivo utility con las constantes que empleará model.
Hasta este punto sabemos que model va a seleccionar aleatoriamente entre las tres listas (letras, números y signos de puntuación). Pero, no puede ser 1/3 de probabilidad para cada uno, ya que existe riesgo de que se genere una contraseña con muchos números o signos de puntuación.
<h3>Solución al problema del abuso de caracteres</h3>Para solucionar este problema basta con agregar una probabilidad de que se consiga una de las tres listas. Entonces, si analizamos bien, la solución será generar un número aleatorio entre 1-100 y asignarle un valor tope a cada una de las constantes.
El primer valor se podrá elegir libremente entre 1-100 y expresará (explícitamente) la probabilidad de que se consiga este valor.
Para asignar la probabilidad de la segunda constante deberemos sumarle al primer valor la probabilidad de que consigamos este segundo valor (Sí, puede sonar confuso pero cuando veas la imagen inferior lo entederás claramente).
El último y tercer valor siempre será 100 ya que se ajustará automáticamente a su probabilidad a causa de la segunda constante.
Entonces, ¿Cómo se eligieron estos valores? Fácil, me encargué de tomar 100 muestras de contraseñas aleatorias generadas por otro generador de contraseñas famoso: LastPass. Después de tomar las 100 muestras y clasificar cuantos números y signos de puntuación habían en una extensión promedio de 11 caracteres (y aplicar un poco de estadística) hallé la probabilidad de que aparezca cada tipo de caracter (letras 69%, números 10% y puntuacioón 21%).
<h3>Model</h3>Ahora, con las constantes creadas en utility.py podemos empezar a escribir el código de model.py.
Primero, importaremos el archivo con las constantes y la librería random con randint y choice.
randint: Nos permitirá obtener un número entero entre el rango que le especifiquemos.
choice: Nos permitirá obtener un elemento aleatorio de una secuencia (en este caso: las listas de caracteres).
Luego, consideraremos que para acceder (como indica nuestro gráfico/diagrama) a los atributos de entity deberemos crear un objeto entity. Por lo tanto, el constructor de model se encargará de crear un objeto de esta clase.
Como se ve en la imagen, se añadió un atributo encapsulado vacío donde posteriormente se guardará la contraseña generada.
El primer método lo llamamos generate (generar) y con un parámetro length (longitud) nos permitirá generar una contraseña de esa longitud gracias al ciclo for.
En cada iteración se generará un número entre 1 y 100 con randint que después determinará que tipo de caracter se utilizará (letras, puntuacion o digitos). Posteriormente, se empleará choice para elegir un elemento aleatorio de la lista.
Esto lo haremos accediendo al obj de la clase Password que nos retorna la lista de esos caracteres.
Finalmente, nuestro método get_password convertirá la lista self.__password (creada en la línea 11) en una cadena de string que contendrá nuestra contraseña con la longitud deseada.
Siguiendo la misma lógica que la que hicimos con model y entity, en controller tendremos que crear en el constructror un objeto de la clase model como atributo (para acceder a model).
En cuanto a los métodos, emplearemos 4 niveles de fortaleza de nuestra contraseña. Estos niveles los clasificaremos como constantes en utility con números enteros simples. Además, según el nivel de fortaleza de nuestra contraseña pasaremos como parámetro la longitud que esta tendrá al obj de la clase Model.
Por lo tanto, tendremos que crear otras cuatro constantes que contengan el valor de la longitud que se tendrá. De este modo, el archivo utility quedará de la siguiente forma:
Constante | Número de caracteres |
---|---|
LENGTH_S | 6 |
LENGTH_M | 8 |
LENGTH_L | 12 |
LENGTH_XL | 16 |
En cuanto al archivo controller:
El archivo view es donde vamos a empezar realizar la interfaz gráfica de nuestro programa. Esta interfaz debe permitir al usuario seleccionar el nivel de fortaleza de la contraseña.
Sin embargo, preguntarle directamente al usuario puede ocasionar de que él nunca genere una contraseña que diga “easy” o “fácil”. Por lo que, para términos prácticos utilizaremos el término de longitud: corta, mediana, larga y extra larga (short,medium, large y extra large).
La interfaz también debe tener botones que posibiliten al usuario:
Empezaremos importando todas la librerrías que ocuparemos: Ttk y Tkinter. Adicionalmente, importaremos el archivo controller.py que se encargará de solicitar y retornarnos la contraseña con los datos que le pasemos.
A continuación, visualizaremos la siguiente imagen que detalla el código a escribir con la explicación de lo que hace cada una de las líneas.
Explicar cada una los widgets, sus parámetros, funcionalidades y demás hubiera sido exhaustivo y rellenado de teoría no tan provechosa. Ya que esta librería se aprende con la práctica y no con la explicación. Por ese mismo motivo, al final de tutorial he dejado los links a la documentación utilizada para el desarrollo de este proyecto. Así como el link al repositorio en GitHub para que puedas descargarlo y empeazr a experimentar con él y hacer variantes del mismo con tus propias ideas.
El código (sin tanto comentario que lo explique y como se encuentra en GitHub) queda de la siguiente forma:
Puedes acceder al repositorio del proyecto en Github desde aquí para descargar todo el proyecto y visualizarlo/modificarlo más rápidamente.
A continuación, dejo links para acceder a la documentación de las librería empleadas. Los links están en inglés, pero, al ser la página oficial de Python, permite cambiar el idioma en una pestaña ubicada en la parte superior izquierda.
Librerías básicas:
Librerías avanzadas:
Complementario:
¡Listo! Eso es todo por este tutorial, espero que hayas podido comprender las bases del mismo y que puedas practicarlo con otros ejemplos más “sencillos” o “cortos”.
Para ser honesto, todo esto puede parecer que tomó mucho tiempo de desarrollar, pero no tomó más de 40 minutos. Donde la gran parte del tiempo me tomó utilizar Tkinter y ttk (ya que no recordaba en su totalidad la sintaxis y había que alinear los elementos manualmente)
Además, gracias a la modularidad del mismo, durante el desarrollo se me fueron ocurriendo varias ideas las cuales pude implementar sin problemas en cuestión de segundos.
Por ejemplo, cuando ya tenía la interfaz gráfica terminada se me ocurrió añadir una opción de una contraseña más corta (de 6 caracteres) y solo tuve que añadir dos constantes, aumentar un elif y agregar un radio button. Todo eso no me tomó más de: 25 segundos y ya tenía esta nueva característica funcionando perfectamente sin corromper el código.
¡No tengas miedo a experimentar con tus ideas! Recuerda, la práctica hace al maestro.
Muchas gracias si llegaste hasta aquí y felicidades por comprender las bases de este proyecto 👏🎉.
Encantado con tu proyecto!
Solo que tengo un problema, no puedo visualizar la interfaz gráfica,
espero que me puedas ayudar, gracias!!
Igual tengo problemas con la interfaz y el código en GitHub se cayó