Cómo evitar rutas predecibles usando Hashids en Laravel

Laravel Hashids

Posiblemente te puedes estar preguntando: para que carajos necesitas saber cómo evitar rutas predecibles usando Laravel Hashids.

Y bueno la razón es muy sencilla, si no lo habías pensado cuando haces peticiones similares a esta api/products/N donde N es un valor numérico que corresponde al campo Id de tu tabla o similar, es como otorgar una invitación a que un usuario externo de forma muy sencilla pueda obtener buena parte de tu información adivinando el siguiente valor numérico en tus rutas y lo peor es que puede llegar a automatizar este proceso y obtener tu información sin interactuar con tu aplicación o mediante peticiones directas a tu API REST si es el caso.

Para evitar esto vamos a usar Laravel Hashids, que es un paquete para Laravel que en términos generales nos ayuda a ofuscar un valor numérico de tal forma que, si paso el valor 19 Laravel Hashids lo convierte a una cadena similar a vGk2WnwePp. todo esto se hace de forma que el proceso es reversible así que podemos recuperar el valor original.

De esta forma podemos hacer que las rutas que depende de un id, de nuestra base de datos no pueda determinarse de forma sencilla.

¿Por qué Laravel Hashids?

La realidad, porque es el que necesito en este momento, pero obviamente no es la única alternativa para realizar esto.

existen otras opciones como Laravel Optimus, que esencialmente hace lo mismo que Laravel Hashids pero este ultimo codifica los ids a un valor numérico.

Otras opciones es utilizar UUID y remplazar los id auto numéricos.

Bien, dicho esto vamos a comenzar con un breve paseo a Laravel Hashids.

Instalar Laravel Hashids

Esta parte creo que no requiere muchas explicaciones.

Si estas trabajando con Laravel 5.5 tienes que especificar la versión 3.3.

Configuración

Hashid tien la opción de operar con diferentes “conexiones” para configurar estas opciones requerimos ejecutar el vendor:publish. 

$ php artisan vendor:publish

Ahora solo edita el archivo config/hashids.php, para nuestro ejemplo vamos a usar la conexión por default.

salt: es una cadena de texto que sive como semilla, recuerda no usar la del ejemplo!.

length: corresponde a la longitud que tendrá la cadena generada por hashid.

Como usar Hashids

El uso es muy sencillo

Debes tomar en cuenta que la decodificación regresa un arreglo; en nuestro ejemplo ($decode)

Manos a la obra.

Vamos a suponer que tenemos un Api muy simple que nos proporciona información sobre productos, el controlador para este ejemplo luce de la siguiente forma.

Por cierto es muy importante que tomes esto como un ejemplo muy simplificado de un API, así que no lo uses para cosas de producción solo toma la idea general para implementar el uso de Hashids en tus proyectos.

Bien, dicho esto lo que requerimos es tener una forma de lograr que todas las peticiones que requieren de un id en la ruta (get, put, patch, delete) ahora se codifiquen para reducir el riesgo de predecir el rango de ids auto numéricos con los que cuenta nuestra base de datos.

Así que para lograr esto, necesitamos codificar el id y luego decodificar cuando lo recuperemos en el request, pero tranquilo, esto es muy sencillo si utilizamos Route model binding.

Como cambiar el Route Binding

Como debes de imaginar tenemos que decirle a Laravel como va a resolver nuestro modelo Product usando Laravel Hashids y esto lo vamos a realizar en el RouteServiceProvider de la siguiente forma.

Excelente, con este cambio si intentas por ejemplo acceder a api/products/1 o cualquier otro id Laravel te debe de regresa la siguiente respuesta.

Pero seguimos revelando nuestros ids auto incrementales; por ejemplo si haces una petición como api/producs, vas a obtener todos los productos con su id numérico. Para resolver este detalle solo tenemos que hacer que el ProductResource entregue los ids codificados mediante Laravel Hashids.

Como cambiar el API Resource

Asi que vamos a hacer ese cambio.

Muy bien ya casi tenemos todo listo, ya solo falta modificar el modelo Product para agregar el método getHashId()

Modificando el modelo

Dado que vamos a tener mas de un modelo, vamos a crear un Trait que se encargue del trabajo duro de codificar los ids.

Ahora solo tenemos que usar el Trait en nuestros modelo y todo estará listo!

 

¿Que sigue?

Los comentarios obviamente!.

Muy bien hemos visto que podemos ofuscar los ids que exponemos en nuestras rutas, con la finalidad de evitar que sean predecibles.

Con esto evitamos también que puedan contar el numero aproximado de registros que tenemos, ademas complicamos la posibilidad de que obtengan información de nuestra base de datos recorriendo de forma secuencial nuestras rutas.

Pero mucho ojo, que esto no es a prueba de balas!, debes de estar consciente que esto no agrega seguridad a tu aplicación; su tarea simplemente es evitar que adivinen tus rutas.

Es importante que tomes medidas adicionales como paginar tus resultados y limitar el numero de peticiones que puede hacer un usuario en un periodo de tiempo, ademas recuerda de tener un sistema de permisos adecuado para evitar que los usuario “miren” en los registros en los cuales no tiene permisos.

Y claro muy importante no reveles la estructura de tu base de datos en las respuestas.

Espero que este articulo te haya gustado y si te fue útil, por favor comparte este articulo y también comparte con nosotros lo aprendido y si tienes otra forma de hacer esto, estaré encantado de saber como lo estas haciendo.

Así que deja un comentario!.

 

Comparte este artículo

Entra en la discusión y deja tu comentario

Veces