Uno de los principios mas importantes en el desarrollo web es que no puedes confiar en nada de lo que viene en los formularios de usuario. Necesitas validar todos los datos de entrada antes de usarlos. Muchos sitios web son afectados por este problema, lo que es simplemente crucial.
Existen dos maneras de verificar datos de formularios, que son usadas comunmente. La primera es la validación del lado del cliente en el front end, y la segunda es la validación del lado del servidor, en el back end. En esta sección vamos a hablar sobre la validación del lado del servidor.
Algunas veces requerimos que los usuarios ingresen algunos campos, pero ellos fallan completándolos. Por ejemplo, en la sección anterior, nosotros requerimos un nombre de usuario. Puedes usar la función len
para obtener el tamaño de un campo para asegurarte que se ha ingresado algo.
if len(r.Form["username"][0])==0{
// code for empty field
}
r.Form
trata diferente a las entradas que son de distinto tipo cuando están vacíos. Para cuadros de textos, áreas de texto y campos de archivos, retorna una cadena vacía, para botones circulares y cajas de chequeo, a veces ni siquiera se crean los tipos. En cambio, vas a tener problemas accediendo a los elementos correspondientes. Por esto, es mas seguro usar r.Form.Get()
para obtener los valores de los campos de una manera que siempre van a retornar vacío si el valor no existe. Por otra parte, r.Form.Get()
solo puede obtener un valor al tiempo, así que necesitas usar r.Form
para obtener un mapa de los valores.
Algunas veces necesitamos números mas allá de texto en un campo. Por ejemplo, digamos que necesitas la edad de un usuario como un entero solamente, es decir: 50 o 10, en vez de "lo suficientemente viejo" u "hombre jóven". Si requerimos un número positivo, podemos convertir el valor al tipo int
y luego procesarlo:
getint,err:=strconv.Atoi(r.Form.Get("age"))
if err!=nil{
// error occurs when convert to number, it may not a number
}
// check range of number
if getint >100 {
// too big
}
Otra manera de realizar esto es usando expresiones regulares:
if m, _ := regexp.MatchString("^[0-9]+$", r.Form.Get("age")); !m {
return false
}
Para propósitos de eficiencia, las expresiones regulares no son eficientes, sin embarglo las expresiones regulares simples son lo suficientemente rápidas. Si estas familiarizado con las expresiones regulares, es una manera muy conveniente de verificar datos. Nota que Go usa la sintaxis RE2, entonces todos los caracteres de UTF-8 están soportados.
Algunas veces, necesitamos que los usuarios ingresen su nombre en chino, y necesitamos verificar que todos estén en chino, en vez de caracteres al azar. Para la verificación del chino, las expresiones regulares son la única manera de conseguirlo:
if m, _ := regexp.MatchString("^[\\x{4e00}-\\x{9fa5}]+$", r.Form.Get("realname")); !m {
return false
}
Algunas veces necesitamos que los usuarios solo ingresen letras del Inglés, por ejemplo algún nombre en inglés como astaxie en vez de asta谢. Podemos verificar esto usando la siguiente expresión regular.
if m, _ := regexp.MatchString("^[a-zA-Z]+$", r.Form.Get("engname")); !m {
return false
}
Si queremos si el usuario ha ingresado una dirección de correo electrónico válida, puedes usar la siguiente expresión regular:
if m, _ := regexp.MatchString(`^([\w\.\_]{2,10})@(\w{1,}).([a-z]{2,4})$`, r.Form.Get("email")); !m {
fmt.Println("no")
}else{
fmt.Println("yes")
}
Digamos que vamos a requerir un elemento de una lista desplegable, pero en vez de esto, tenemos un valor fabricado por hackers. ¿Cómo evitamos que esto pase?
Suponga que tenemos el siguiente <select>
<select name="fruit">
<option value="apple">apple</option>
<option value="pear">pear</option>
<option value="banana">banana</option>
</select>
Podemos usar la siguiente estrategia para limpiar la entrada:
slice:=[]string{"apple","pear","banana"}
for _, v := range slice {
if v == r.Form.Get("fruit") {
return true
}
}
return false
Todas las funciones que he mostrado arriba están en mi proyecto de código abierto para operar con segmentos y mapas: https://github.com/astaxie/beeku
Si queremos saber cuando un usuario es femenino o masculino, podríamos usar un botón circular, retornando 1 para femenino y 2 para masculino. Sin embargo, algún niño que acaba de leer su primer libro sobre HTTP decide enviar un 3. ¿Nuestro programa levantará una excepción? Como puedes ver, necesitamos usar el mismo método que usamos para la lista desplegable para asegurarnos sobre los valores que son ingresados a nuestro botón circular.
<input type="radio" name="gender" value="1">Femenino
<input type="radio" name="gender" value="2">Masculino
Y usualmente utilizamos el siguiente código para validar las entradas:
slice:=[]int{1,2}
for _, v := range slice {
if v == r.Form.Get("gender") {
return true
}
}
return false
Supon que existen algunas cajas de chequeo para los intereses de los usuarios, y tu no quieres valores extraños aquí tampoco, puedes validarlos de la siguiente manera:
<input type="checkbox" name="interest" value="football">Football
<input type="checkbox" name="interest" value="basketball">Basketball
<input type="checkbox" name="interest" value="tennis">Tennis
En este caso la estrategia de limpieza es un poco diferente a la validación de botones de chequeo y listas desplegables:
slice:=[]string{"football","basketball","tennis"}
a:=Slice_diff(r.Form["interest"],slice)
if a == nil{
return true
}
return false
Supón que quieres que los usuarios ingresen fechas y horas. Go tiene un paquete time
para convertir año, mes y día a la hora correspondiente. Después de eso, es fácil verificarlo.
t := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
fmt.Printf("Go launched at %s\n", t.Local())
Después de eso, también puedes utilizar el paquete time
para mas operaciones, dependiende de tus necesidades.
En esta sección hemos discutido algunos métodos comunes para validar los datos del lado del servidor. Espero que ahora entiendas un poco mas sobre la validación de datos en Go, especialmente como usar las evntajas de las expresiones regulares.
- Índice
- Sección anterior: Procesando la entrada de los formularios
- Siguiente sección: Cross site scripting