Go con Gin, el mega tutorial (VI)

Nómadas, ¿Con ganas de más Go con Gin? Vamos a por ello entonces. La entrada de hoy será corta y hablaremos sobre sesiones, que son y como las utilizaremos.

Índice de la serie

 

Sesiones

El protocolo HTTP es un protocolo sin estado, por lo que se precisa de mecanismos externos al protocolo para conseguir un “protocolo con estado”. Manteniendo un estado entre el servidor y el navegador o cliente nos permite hacer cosas muy interesantes, como por ejemplo, validar un usuario y mantener su sesión activa durante X tiempo. También podríamos ir guardando los elementos comprados en un carro de compra virtual, así el usuario puede ir comprando mientras añade productos a su carro de la compra, etc.

Como se puede apreciar las sesiones son muy importantes en un protocolo sin estado como es el HTTP. Ahora, ¿Cómo las implementamos en Gin? Para ello utilizaremos la librería github.com/gin-contrib/sessions.

Primero pasos con las sesiones

La instalación de la librería en nuestro proyecto es muy sencillo, ya lo hemos hecho en otras ocasiones, dep ensure -add github.com/gin-contrib/sessions y listo.

La otra parte, la que nos interesa de verdad. ¿Cómo utilizamos la librería? Aquí la cosa se complica un poco más, pues hemos hablado de las bondades de utilizar sesiones, pero no de como se implementan. Las sesiones son al fin y al cabo, y en su forma más básica, un fichero, tal cual, un fichero.

Te puede interesar  DEP, el gestor de librerías y vendoring de Go

La verdad que disponer de las sesiones en un fichero pues es bastante ineficiente y en muchas ocasiones inseguro. Pero además de un fichero, las sesiones se pueden almacenar en bases de datos, memoria, galletas (cookies) y alguno más. Nosotros por ahora usaremos las cookies.

El código que vamos a modificar es principalmente en los ficheros webapp/router/main.go y webapp/router/handlers/handlers.go. En el primero configuraremos Gin para que pueda utilizar sesiones. Esto es utilizando un handler especial, y que normalmente se llama middleware. El segundo fichero será donde hagamos uso de las sesiones.

Tal como ya hicimos en el capítulo 4 vamos a crear una función para preparar la configuración referente a las sesiones en la función NewServer. La función que utilizaremos es RegisterSession.

Serializado de datos

Antes de continuar con las sesiones es necesario comentar la forma en la que se transfieren las sesiones entre el servidor y el cliente o servidor base de datos.

En las sesiones podemos almacenar casi cualquier objeto. Hasta aquí genial y muy útil. Pero el objeto almacenado debe ser serializado, así que hay que registrar el objeto que queremos serializar en la librería utilizada para serializar los objetos, en Go la librería es gob.

Esto lo haremos con la función RegisterSerializers, la cual llamaremos al inicio de la función NewServer. De este modo, todos los objetos de la sesión serán serializados correctamente.

Usando las sesiones

Continuemos con las sesiones. Ahora ya podemos serializar las sesiones, así que nos queda inicializar las sesiones en Gin.

En la función RegisterSession primero creamos una cadena de 32 caracteres aleatorios. Después creamos una coockie con el nombre goblog y la cadena aleatoria para poder cifrar el contenido de la cookie y que no quede visible o texto plano en la parte del cliente.

Te puede interesar  Go con Gin, el mega tutorial (VII)

Con esto tenemos las sesiones listas para usarlas en los handlers.

Antes de explicar el uso de las sesiones en los handlers comentaremos que hemos añadido un grupo de handlers. Esto significa que podemos definir un middleware para que todas las URI dependientes del grupo de handlers pasen por el middleware y cumplan las condiciones que deseamos, como por ejemplo validar si son usuarios autenticados o no.

Si nos fijamos en las líneas 8 y 9 vemos como se define la URI /logout que debe estar accesible solo a usuarios autenticados.

Como se puede ver en la línea 8 se define un handler Authenticated para validar si los usuarios son validos o no.

Las líneas 2 y 3 nos sirven para recuperar la sesión del contexto de la petición y el objeto del usuario. Comprobamos que el objeto usuario no sea nulo, así podemos comprobar si el usuario está autenticado o no. Si lo está, ejecutamos el siguiente handler, esto es con c.Next(), y el siguiente handler se corresponde con el que procesa la URI y la petición. En caso contrario se muestra la página principal con un mensaje de error.

Handler con autenticación

Vamos a explicar el uso de sesiones con un handler en concreto, pues al final es siempre igual y además el código está disponible en Github.

Explicaremos el handler del login. Partiendo del último código que está disponible en Github.

Lo primero que hacemos es comprobar si existe una sesión y si el objeto user está disponible, de estarlo, entones guardamos el objeto user en una variable. Acto seguido comprobamos si el usuario está autenticado, para ello consultamos el valor del campo IsAuthenticated. Si el usuario está autenticado no requiere ser autenticado, así que mostramos la página principal. Fijaros como añadimos el usuario en los objetos de la plantilla (esto lo veremos más abajo).

Te puede interesar  Telegram bots en golang (II)

Si el usuario no está autenticado procedemos tal cual hacíamos hasta ahora.

Cuando la petición es del tipo POST y después de comprobar que el usuario sea valido debemos añadir el objeto usuario en la sesión, para que en los próximos handlers hagan lo oportuno según si el usuario está autenticado o no.

Las sesiones no tienen mucho más, solo hay que tener en cuenta donde hay que validar que el usuario esté autenticado o no.

Para finalizar, vamos a mostrar como interactuar con los objetos de usuario en las plantillas. Hemos actualizado la plantilla parcial webapp/template/partials/menu.tpl para que muestre el nombre del usuario.

Bueno, ya hemos terminado el post sobre las sesiones, en el siguiente post crearemos las paginas de los perfiles (profiles) y el uso de avatares.

Nos vemos pronto.

Go con Gin, el mega tutorial (VI)
Etiquetado en:                 

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *