Skip to content

Commit cc95a03

Browse files
author
ma0
committed
complete chapter 4 translation to spanish
1 parent d98aaa2 commit cc95a03

File tree

6 files changed

+456
-10
lines changed

6 files changed

+456
-10
lines changed

Diff for: es/03.4.md

+10-10
Original file line numberDiff line numberDiff line change
@@ -176,21 +176,21 @@ En escenarios mas complejos también podemos utilizar este método, la ventaja e
176176

177177
Vamos a echar un vistazo a la lista de flujo de ejecución en conjunto.
178178

179-
- Se llama http.HandleFunc
179+
- Se llama `http.HandleFunc`
180180
1. Se Llama HandleFunc de DefaultServeMux
181181
2. Se Llama Handle de DefaultServeMux
182182
3. Se agregan las reglas del enrutamiento a map[string]muxEntry de DefaultServeMux
183-
- Se llama http.ListenAndServe (":9090" , nil )
183+
- Se llama `http.ListenAndServe(":9090" , nil)`
184184
1. Se instancia el servidor
185-
2. Llama ListenAndServe del Servidor
186-
3. Llama net.Listen ( " tcp" , addr ) para escuchar en el puerto .
185+
2. Se Llama ListenAndServe del Servidor
186+
3. Se Llama net.Listen ( "tcp" , addr ) para escuchar en el puerto.
187187
4. Iniciar un bucle, y aceptar las solicitudes en el cuerpo del bucle.
188-
5. Instanciada una Conn se empieza una goroutine para cada solicitud : ir c.serve ().
189-
6. Lee petición de datos : w , err : = c.readRequest ().
190-
7. Comprueba si el controlador está vacío, si está vacíoutiliza DefaultServeMux .
191-
8. Llama al controlador de ServeHTTP
192-
9. Ejecutar código en DefaultServeMux en este caso.
193-
10. Elije el controlador URL y ejecutar código del controlador en esta seccion: mux.handler.ServeHTTP ( w , r)
188+
5. Instanciar una Conn y se empieza una goroutine para cada solicitud : `go c.serve ()`
189+
6. Se Lee petición de datos : `w , err : = c.readRequest ()`
190+
7. Se Comprueba si el controlador está vacío, si está vacíoutiliza DefaultServeMux .
191+
8. Se Llama al controlador de ServeHTTP
192+
9. Se Ejecuta el código en DefaultServeMux en este caso.
193+
10. Elije el controlador URL y ejecutar código del controlador en esta seccion: `mux.handler.ServeHTTP (w , r)`
194194
11. Cómo elegir handler:
195195
A. Normas de router de verificación para esta URL.
196196
B. Llamar ServeHTTP en ese controlador, si es que existe.

Diff for: es/04.2.md

+141
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
# 4.2 Verificando las entradas
2+
3+
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.
4+
5+
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.
6+
7+
## Campos requeridos
8+
9+
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.
10+
```
11+
if len(r.Form["username"][0])==0{
12+
// code for empty field
13+
}
14+
```
15+
`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.
16+
17+
## Números
18+
19+
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:
20+
```
21+
getint,err:=strconv.Atoi(r.Form.Get("age"))
22+
if err!=nil{
23+
// error occurs when convert to number, it may not a number
24+
}
25+
26+
// check range of number
27+
if getint >100 {
28+
// too big
29+
}
30+
```
31+
Otra manera de realizar esto es usando expresiones regulares:
32+
```
33+
if m, _ := regexp.MatchString("^[0-9]+$", r.Form.Get("age")); !m {
34+
return false
35+
}
36+
```
37+
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](http://code.google.com/p/re2/wiki/Syntax), entonces todos los caracteres de UTF-8 están soportados.
38+
39+
## Chino
40+
41+
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:
42+
```
43+
if m, _ := regexp.MatchString("^[\\x{4e00}-\\x{9fa5}]+$", r.Form.Get("realname")); !m {
44+
return false
45+
}
46+
```
47+
## Letras del Inglés
48+
49+
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.
50+
```
51+
if m, _ := regexp.MatchString("^[a-zA-Z]+$", r.Form.Get("engname")); !m {
52+
return false
53+
}
54+
```
55+
## Correo electrónico
56+
57+
Si queremos si el usuario ha ingresado una dirección de correo electrónico válida, puedes usar la siguiente expresión regular:
58+
```
59+
if m, _ := regexp.MatchString(`^([\w\.\_]{2,10})@(\w{1,}).([a-z]{2,4})$`, r.Form.Get("email")); !m {
60+
fmt.Println("no")
61+
}else{
62+
fmt.Println("yes")
63+
}
64+
```
65+
## Lista desplegable
66+
67+
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?
68+
69+
Suponga que tenemos el siguiente `<select>`
70+
```
71+
<select name="fruit">
72+
<option value="apple">apple</option>
73+
<option value="pear">pear</option>
74+
<option value="banana">banana</option>
75+
</select>
76+
```
77+
Podemos usar la siguiente estrategia para limpiar la entrada:
78+
```
79+
slice:=[]string{"apple","pear","banana"}
80+
81+
for _, v := range slice {
82+
if v == r.Form.Get("fruit") {
83+
return true
84+
}
85+
}
86+
return false
87+
```
88+
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](https://github.com/astaxie/beeku)
89+
90+
## Botones circulares
91+
92+
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.
93+
```
94+
<input type="radio" name="gender" value="1">Femenino
95+
<input type="radio" name="gender" value="2">Masculino
96+
```
97+
Y usualmente utilizamos el siguiente código para validar las entradas:
98+
```
99+
slice:=[]int{1,2}
100+
101+
for _, v := range slice {
102+
if v == r.Form.Get("gender") {
103+
return true
104+
}
105+
}
106+
return false
107+
```
108+
## Cajas de chequeo
109+
110+
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:
111+
```
112+
<input type="checkbox" name="interest" value="football">Football
113+
<input type="checkbox" name="interest" value="basketball">Basketball
114+
<input type="checkbox" name="interest" value="tennis">Tennis
115+
```
116+
En este caso la estrategia de limpieza es un poco diferente a la validación de botones de chequeo y listas desplegables:
117+
```
118+
slice:=[]string{"football","basketball","tennis"}
119+
a:=Slice_diff(r.Form["interest"],slice)
120+
if a == nil{
121+
return true
122+
}
123+
124+
return false
125+
```
126+
## Fecha y Hora
127+
128+
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.
129+
```
130+
t := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
131+
fmt.Printf("Go launched at %s\n", t.Local())
132+
```
133+
Después de eso, también puedes utilizar el paquete `time` para mas operaciones, dependiende de tus necesidades.
134+
135+
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.
136+
137+
## Enlaces
138+
139+
- [Índice](preface.md)
140+
- Sección anterior: [Procesando la entrada de los formularios](04.1.md)
141+
- Siguiente sección: [Cross site scripting](04.3.md)

Diff for: es/04.3.md

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# 4.3 Cross site scripting
2+
3+
Hoy los sitios web tienen mucho contenido dinámico en orden de mejorar la experiencia de usuario, lo que significa que debemos proveer información dinámica en función de cada comportamiento individual, desafortunadamente, los sitios web dinámicos son suceptibles a ataques maliciosos conocidos como "Cross site scripting" (abreviado "XSS"). Los sitios web estáticos no son vulnerables a este tipo de ataque.
4+
5+
Los atacantes usualmente inyectan código malicioso como Javascript, VBScript, ActiveX o Flash en sitios que tienen vulnerabilidades. Una vez que han conseguido enyectar sus scripts, la información del usuario puede ser robada y tu sitio web puede ser inundado de Spam. Los atacantes también pueden cambiar las configuraciones de los usuarios como sea que ellos quieran.
6+
7+
Si deseas prevenir este tipo de ataques, deberías combinar las siguientes dos aproximaciones
8+
9+
- Validar toda la información de los usuarios, que discutimos en la sección pasada.
10+
- Manejar cuidadosamente la información enviada por los clientes en orden de prevenir cualquier inyección de scripts hecha desde los navegadores.
11+
12+
Entonces ¿Cómo podemos haces estas dos cosas en Go? Afortunadamente, el paquete `http/template` tiene algunas funciones que nos permiten escapar los datos como sigue:
13+
14+
- `func HTMLEscape(w io.Writer, b []byte)` escapa b to w.
15+
- `func HTMLEscapeString(s string) string` retorna una cadena después de escaparla de s
16+
- `func HTMLEscaper(args ...interface{}) string` retorna una cadena después de escaparla de algunos argumentos.
17+
18+
Vamos a cambiar el ejemplo de la sección 4.1:
19+
```
20+
fmt.Println("username:", template.HTMLEscapeString(r.Form.Get("username"))) // Imprime en el lado del servidor
21+
fmt.Println("password:", template.HTMLEscapeString(r.Form.Get("password")))
22+
template.HTMLEscape(w, []byte(r.Form.Get("username"))) // Respuesta a los clientes
23+
```
24+
Si alguien trata de ingresar el nombre de usuario como `<script>alert()</script>` podremos ver el siguiente contenido en el navegador.
25+
26+
![](images/4.3.escape.png?raw=true)
27+
28+
Figure 4.3 JavaScript después del escape
29+
30+
Las funciones en el paquete `html/template` nos ayudan a escapar todas las etiquetas HTML. Y ¿qué pasa si queremos imprimir `<script>alert()</script>` en los navegarores? Deberías usar el paquete `text/template`.
31+
```
32+
import "text/template"
33+
...
34+
t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
35+
err = t.ExecuteTemplate(out, "T", "<script>alert('you have been pwned')</script>")
36+
```
37+
Salida:
38+
```
39+
Hello, <script>alert('you have been pwned')</script>!
40+
```
41+
O puedes usar el tipo `template.HTML`:
42+
El contenido variable no va a ser escapado si es del tipo `template.HTML`
43+
Variable content will not be escaped if its type is `template.HTML`.
44+
```
45+
import "html/template"
46+
...
47+
t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
48+
err = t.ExecuteTemplate(out, "T", template.HTML("<script>alert('you have been pwned')</script>"))
49+
```
50+
Salida:
51+
```
52+
Hello, <script>alert('you have been pwned')</script>!
53+
```
54+
Un ejemplo mas de escape:
55+
```
56+
import "html/template"
57+
...
58+
t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
59+
err = t.ExecuteTemplate(out, "T", "<script>alert('you have been pwned')</script>")
60+
```
61+
Salida:
62+
```
63+
Hello, &lt;script&gt;alert(&#39;you have been pwned&#39;)&lt;/script&gt;!
64+
```
65+
## Enlaces
66+
67+
- [Índice](preface.md)
68+
- Sección anterior: [Verificando las entradas](04.2.md)
69+
- Siguiente sección: [Envíos duplicados](04.4.md)

Diff for: es/04.4.md

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# 4.4 Envíos duplicados
2+
3+
No se si alguna vez has visto blogs que tienen uno o mas de un post que son exactamente iguales, pero puedo decirte que es porque un usuario envió dos veces el mismo formulario. Existen muchas cosas que pueden cambiar envíos duplicados; algunas veces los usuarios hacen doble click en el botón de enviar, o quieren modificar el contenido después de postear y usan el botón de atrás. En algunos casos es por una acción intencioanl de usuarios malicioso. Es facil ver como los envíos duplicados pueden generar muchos problemas. Afortunadamente tenemos herramientas para prevenirlos.
4+
5+
La solución es añadir un campo oculto con un único token al formulario, y siempre verificar si el token ha sido procesado con anterioridad. También si quieres usar ajax para enviar un formulario, puedes usar javascript para deshabilitar el botón una vez se ha presionado.
6+
7+
Vamos a mejorar el ejemplo de la sección 4.2:
8+
```
9+
<input type="checkbox" name="interest" value="football">Futbol
10+
<input type="checkbox" name="interest" value="basketball">Basquetbol
11+
<input type="checkbox" name="interest" value="tennis">Tenis
12+
Nombre de usuario:<input type="text" name="username">
13+
Contraseña:<input type="password" name="password">
14+
<input type="hidden" name="token" value="{{.}}">
15+
<input type="submit" value="Ingresar">
16+
```
17+
Nosotros usamos un hash MD5 con la hora actual para generar el token, y agregamos esto a un campo oculto del lado del cliente y a una cookie en el lado del servidor (Capítulo 6). Nosotros usamos este token para verificar si el formulario ha sido enviado.
18+
```
19+
func login(w http.ResponseWriter, r *http.Request) {
20+
fmt.Println("method:", r.Method) // get request method
21+
if r.Method == "GET" {
22+
crutime := time.Now().Unix()
23+
h := md5.New()
24+
io.WriteString(h, strconv.FormatInt(crutime, 10))
25+
token := fmt.Sprintf("%x", h.Sum(nil))
26+
27+
t, _ := template.ParseFiles("login.gtpl")
28+
t.Execute(w, token)
29+
} else {
30+
// log in request
31+
r.ParseForm()
32+
token := r.Form.Get("token")
33+
if token != "" {
34+
// check token validity
35+
} else {
36+
// give error if no token
37+
}
38+
fmt.Println("username length:", len(r.Form["username"][0]))
39+
fmt.Println("username:", template.HTMLEscapeString(r.Form.Get("username"))) // print in server side
40+
fmt.Println("password:", template.HTMLEscapeString(r.Form.Get("password")))
41+
template.HTMLEscape(w, []byte(r.Form.Get("username"))) // respond to client
42+
}
43+
}
44+
```
45+
![](images/4.4.token.png?raw=true)
46+
47+
Figure 4.4 El contenido del navegador después de agregar el Token
48+
49+
Puedes refrescar la página y verás un token diferente cada vez. Esto asegura que cada formulario es único.
50+
51+
Por ahora, puedes prevenir ataques de envíos duplicados añadiendo tokens a tus formularios, pero no puedes prevenir todos los ataques de este tipo, aún hay mucho trabajo por hacer.
52+
53+
## Enlaces
54+
55+
- [Índice](preface.md)
56+
- Sección anterior: [Cross site scripting](04.3.md)
57+
- Siguiente sección: [Subida de archivos](04.5.md)

0 commit comments

Comments
 (0)