Realmente me pone de mal humor que pseudo programadores recomienden validar los datos solamente en Javascript.
Me encanta mantenerme activo en comunidades de programación, ya sea en sitios como Foros del Web, StackOverflow, Google+ y Facebook. Por mi propia sanidad mental, he pensado sinceramente en no participar en esos grupos nunca más porque la cantidad de pésimos consejos abundan. Es imposible recomendar buenas prácticas de programación a todo el mundo porque simplemente no se puede.
Entre las más comunes es la famosa pregunta de:
"¿Cómo valido los datos de mi formulario?"
Y de inmediato abundan los siguientes comentarios:
Uggh... Siempre que veo alguien recomendado validar SOLAMENTE con Javascript, simplemente me vuelve loco.
La validación TIENE QUE TOMAR LUGAR EN AMBOS LADOS DE LA APLICACION! FRONTEND Y BACKEND!
En el front end la validación de los datos no se hace por seguridad, sino por experiencia del usuario!
Explico:
Una aplicación web con una excelente experiencia de usuario (UX) toma los datos en cualquier forma que los provea, y los valida para determinar si la información que ingresó es correcta o no. Darle formato al input del usuario es opcional, pero generalmente no tiene sentido aplicar el formato correcto en el front end y es una tarea que debe realizarse en el backend.
Por ejemplo, si estás validando números de teléfono, un usuario puede escribir los números de teléfono de la manera que se le antoje, y tu aplicación debe saber reconocer las múltiples variaciones de como escribir un número de teléfono:
- (555) 555 5555
- (555)-555-5555
- (555) - 555 - 5555
- 555 - 555 - 5555
- +1 555 555 5555
- 555.555.5555
- (555)555-5555
Los 7 ejemplos anteriores son números de teléfono válidos, y las personas escriben su número de teléfono de diferentes maneras, la validación en el front end solamente sirve para asegurarse de que el usuario está ingresando un número de teléfono "válido" en cualquier formato que el usuario lo ingreso.
Sin embargo, asumir que los datos son seguros e integros sólo porque la información fue validada en Javascript/HTML5 es simplemente negligencia de un programador inepto.
Supongamos que el código de tu formulario es el siguiente:
¿Cuál es el problema del código anterior?
Si, es vulnerable, pero si pensaste en SQL Injection, estás equivocado.
Ese código utiliza prepared statements, lo cual previene ataques de inyección de SQL. Sin embargo, no previene Cross Site Scripting (XSS) Eso quiere decir que si alguien escribe en el campo "Nombre" la siguiente cadena de texto:
<script>alert('Hello world');</script>
Mi aplicación es virtualmente vulnerable a Cross Site Scripting. Sin embargo, dejando la seguridad de la aplicación por un lado y enfocándonos en la integridad de los datos
¿Qué pasaría si quieres escribir una consulta SQL para que te muestre todos los números que empiecen con código de area 868?
Si tu aplicación inserta los datos proveídos por el usuario, sin antes darles el formato adecuado para almacenarlos en tu base de datos, los reportes y consultas siempre serán ineficientes e imprecisas!
Por ejemplo, para el ejemplo anterior, bien podrías escribir una consulta como:
Si tienes experiencia, inmediatamente vas a notar el problema con esa consulta. Si no lo notas, a continuación te lo explico; Tu consulta no va a seleccionar números de teléfono con el siguiente formato:
- (868)555-555
- +52(868)555-555
Dichos números de teléfono no cumplen con la condición en WHERE. Sin embargo, si cumplen con el criterio original de la consulta. El programador "listillo", podría escribir la siguiente consulta:
Nuevamente, si eres programador experimentado, te darás cuenta inmediatamente del problema con esa consulta. Ahora vas a seleccionar los renglones descritos anteriormente, ya que van a cumplir con la condición WHERE, pero también vas a seleccionar los siguientes renglones:
- (555)868-1111
- (123)956-3868
- 555-123-8682
Los cuales son resultados completamente incorrectos. Entonces quedas a la deriva y te preguntas
¿Qué es preferible, seleccionar todos los datos correctos junto con algunos incorrectos o seleccionar algunos datos correctos, sin ninguno incorrecto?
Honestamente, ninguna de las dos. No falta el aún más listillo que dice:
"Bah Alan, escribo una expresión regular en la condición de WHERE y listo!"
Ughh... Supongamos que la expresión regular funcione bien cuando tengas 100, 1000 o incluso 10000 renglones. Cuando tu tabla tenga una cardinalidad con 6 digitos, tu aplicación va a empezar a sufrir, y ni se diga cuando tengas una cardinalidad con 7 digitos.
Cuando utilizas expresiones regulares para extraer datos de una base de datos, el 99% de las ocasiones lo estás haciendo mal.
Al utilizar expresiones regulares en bases de datos, estas obligando al motor de la base de datos que haga un "Full table scan" y comparar cada uno de los renglones en tu base de datos contra tu expresión regular. Ese proceso es extremadamente lento y no se puede escalar, eso sin tomar en cuenta que la evaluación de expresiones regulares también es lenta!
¿Entonces, cuál es la solución?
Valida y darles el formato adecuado a los datos en el backend!
Supongamos que el nombre de una persona, solo puede tener una cantidad máxima de 50 caracteres, y los números de teléfono en tu base de datos van a ser almacenados solamente como números, el siguiente código le da el formato adecuado a tus datos:
Con el código anterior nos aseguramos que el nombre del contacto es exactamente 50 caracteres o menos, que en caso de que contenga input malicioso, esos datos son codificados de tal manera de mitigar el riesgo de XSS y otro tipo de ataques (dije mitigar, no eliminar).
Finalmente, con el numero de teléfono te aseguras de solamente almacenar números, y que el número que estas almacenando es solamente el número y no el código del país.
De la manera anterior, no solamente garantizas que la información almacenada siempre será correcta y coherente, y además de que puedes optimizar la indexación de las tablas e incrementar el desempeño de tus consultas.
Recuerda:
Validar en el front-end es para mejorar la experiencia del usuario, validar en el backend es para garantizar la integridad de los datos y prevenir ataques de usuarios maliciosos.