Skip to content

Commit 3dbde43

Browse files
authored
Merge pull request #1081 from drypa/patch-5
typos fix & code formatting
2 parents f86595e + ca6af50 commit 3dbde43

File tree

1 file changed

+30
-30
lines changed

1 file changed

+30
-30
lines changed

ru/04.4.md

+30-30
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,47 @@
11
# 4.4 Дублирование отправки
22

3-
Не знаю, встречали ли Вы, как на каком-либо блоге или форуме размещено несколько постов подряд с одинаковым содержимым, но я могу сказать Вам, что это происходит по причине того, что отправка постов дублируется пользователем. Это может произойти по многим причинам; иногда пользователь отправляет форму двойным щелчком, или он после отправки решает исправить содержимое поста и нажимает кнопку браузера "Назад". А иногда это - намереные действия злоумышленников. Понятно, что дублирование отправки может привести ко многим проблемам. Поэтому нам нужно принимать эффективные меры для его предотвращения.
3+
Не знаю, встречали ли Вы, как на каком-либо блоге или форуме размещено несколько постов подряд с одинаковым содержимым, но я могу сказать Вам, что это происходит по причине того, что отправка постов дублируется пользователем. Это может произойти по многим причинам; иногда пользователь отправляет форму двойным щелчком, или он после отправки решает исправить содержимое поста и нажимает кнопку браузера "Назад". А иногда это - намеренные действия злоумышленников. Понятно, что дублирование отправки может привести ко многим проблемам. Поэтому нам нужно принимать эффективные меры для его предотвращения.
44

5-
Решением этой задачи является добавление в форму скрытого поля с уникальным токеном и проверка этого токена перед перед обработкой введенных данных. А если для отправки формы Вы используете Ajax, можно после того, как данные отправлены, сделать кнопку отправки неактивной.
5+
Решением этой задачи является добавление в форму скрытого поля с уникальным токеном и проверка этого токена перед обработкой введенных данных. А если для отправки формы Вы используете Ajax, можно после того, как данные отправлены, сделать кнопку отправки неактивной.
66

77
Давайте усовершенствуем пример из раздела 4.2:
8-
8+
```html
99
<input type="checkbox" name="interest" value="football">Футбол
1010
<input type="checkbox" name="interest" value="basketball">Баскетбол
1111
<input type="checkbox" name="interest" value="tennis">Теннис
1212
Имя:<input type="text" name="username">
1313
Пароль:<input type="password" name="password">
1414
<input type="hidden" name="token" value="{{.}}">
1515
<input type="submit" value="Login">
16-
16+
```
1717
Для того, чтобы сгенерировать токен, мы используем хэш MD5 (временная отметка), и добавляем его как в скрытое поле формы ввода данных на стороне клиента, так и в сессионный куки на стороне сервера (см. Раздел 6). Мы можем использовать этот токен для того, чтобы проверить, отправлялись ли уже данные с этой формы:
18-
19-
func login(w http.ResponseWriter, r *http.Request) {
20-
fmt.Println("method:", r.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-
// запрос данных о входе
31-
r.ParseForm()
32-
token := r.Form.Get("token")
33-
if token != "" {
34-
// проверяем валидность токена
35-
} else {
36-
// если нет токена, возвращаем ошибку
37-
}
38-
fmt.Println("username length:", len(r.Form["username"][0]))
39-
fmt.Println("username:", template.HTMLEscapeString(r.Form.Get("username"))) // печатаем на стороне сервера
40-
fmt.Println("password:", template.HTMLEscapeString(r.Form.Get("password")))
41-
template.HTMLEscape(w, []byte(r.Form.Get("username"))) // отвечаем клиенту
42-
}
18+
```Go
19+
func login(w http.ResponseWriter, r *http.Request) {
20+
fmt.Println("method:", r.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+
// запрос данных о входе
31+
r.ParseForm()
32+
token := r.Form.Get("token")
33+
if token != "" {
34+
// проверяем валидность токена
35+
} else {
36+
// если нет токена, возвращаем ошибку
37+
}
38+
fmt.Println("username length:", len(r.Form["username"][0]))
39+
fmt.Println("username:", template.HTMLEscapeString(r.Form.Get("username"))) // печатаем на стороне сервера
40+
fmt.Println("password:", template.HTMLEscapeString(r.Form.Get("password")))
41+
template.HTMLEscape(w, []byte(r.Form.Get("username"))) // отвечаем клиенту
4342
}
44-
43+
}
44+
```
4545
![](images/4.4.token.png?raw=true)
4646

4747
Рисунок 4.4 Содержимое браузера после добавления токена

0 commit comments

Comments
 (0)