11 KiB
4.2 Проверка введенных данных
Одним из наиболее важных правил веб-разработки является то, что нельзя доверять никаким данным, поступившим из пользовательских форм. Вы должны проверять все входящие данные перед тем, как их использовать. Множество веб-сайтов было затронуто этой очень серьезной проблемой.
Существует два наиболее часто используемых способа проверить данные. Один - это проверка средствами Javascript на стороне браузера, а второй - проверка на стороне сервера. В этом разделе мы поговорим о проверке данных средствмаи сервера.
Поля, обязательные к заполнению
Иногода требуется, чтобы пользователь заполнил определенные поля, но они этого не делают; например, в предыдущем разделе, когда нам тербовалось имя пользователя. Мы можем использовать функцию len, чтобы получить длину строки в поле, чтобы быть уверенными, что пользователь заполнил его:
if len(r.Form["username"][0])==0{
// код, выполняемый, если поле оказалось пустым
}
r.Form обрабатывает незаполненные поля различными способами в зависимтсти от их типа. Для пустых текстовых полей, текстовых областей и загружаемых файлов она возвращает пустую строку; для радиокнопок и чекбоксов просто не создаются соответствующие значения. Вместо этого при попытке доступа к ним Вы получите ошибку. Поэтому для получения значений безопаснее использовать r.Form.Get(), так как эта команда всегда возвращает пустые значения. С другой стороны, r.Form.Get() может получить только одно значение за один вызов, поэтому длят того, чтобы получиьт карту значений, нужно использовать r.Form.
Числа
Sometimes you only need numbers for the field value. For example, let's say that you require the age of a user in integer form only, i.e 50 or 10, instead of "old enough" or "young man". If we require a positive number, we can convert the value to the int type first, then process it.
Иногда в значениями поля могут быть толко числа. Например, Вам нужно получить возраст пользователя в целочисленном виде, т.е. 50 или 10, вместо "довольно взрослый" или "молодой человек". Если нам нужно положительное число, мы можем сначала конвертировать значение поля в тип int, а затем уже работать с ним:
getint,err:=strconv.Atoi(r.Form.Get("age"))
if err!=nil{
// если значение не конвертируется в целое число, то было введено не целое число
}
// проверяем диапазон значений
if getint >100 {
// слишком много
}
Другой способ проверки - это регулярные выражения:
if m, _ := regexp.MatchString("^[0-9]+$", r.Form.Get("age")); !m {
return false
}
Вообще регулярные выражения неэффективны в плане производительности, но простые регулярные выражения довольно быстры. Если Вы с ними знакомы, то их использование может быть довольно-таки удобным способом проверить данные. Имейте в виду, что Go использует RE2, что означает, что при работе с регулярными выражениями в Go поддерживаются все символы UTF-8.
Китайские символы
Иногда нам нужно от пользователей, чтобы они вводили свои китайские имена, и нам нужно проверять, что они используют китайские, а не случайные символы. Для осуществления этой задачи регулярные выражения - единственный способ.
if m, _ := regexp.MatchString("^[\\x{4e00}-\\x{9fa5}]+$", r.Form.Get("realname")); !m {
return false
}
Английские буквы
Sometimes we need users to input only English letters. For example, we require someone's English name, like astaxie instead of asta谢. We can easily use regular expressions to perform our verification. Иногда нужно, чтобы пользователь вводил только английские буквы. Например, нам нужно, чтобы пользователь вводил свое имя по-английски, например, astaxie, а не asta谢. Чтобы легко осуществить такую проверку, можно воспользоваться регулярными выражениями:
if m, _ := regexp.MatchString("^[a-zA-Z]+$", r.Form.Get("engname")); !m {
return false
}
(*** Прим. переводчика на русский язык - для русского языка регулярка будет выглядеть как "[А-аЯ-яЁё]+$" ***)
Адрес E-mail
Если Вам нужно узнать, ввел ли пользователь корректный адрес E-mail, можно использовать следующее регулярное выражение:
if m, _ := regexp.MatchString(`^([\w\.\_]{2,10})@(\w{1,}).([a-z]{2,4})$`, r.Form.Get("email")); !m {
fmt.Println("нет")
}else{
fmt.Println("да")
}
Выпадающий список
Let's say we require an item from our drop down list, but instead we get a value fabricated by hackers. How do we prevent this from happening? Допустим, нам нужно получить значение из выпадающего списка, но вместо этого мы получаем значение, сфабрикованное хакерами. Как предотвратить такой случай?
Предположим, у нас есть следующий <select>:
<select name="fruit">
<option value="apple">Яблоко</option>
<option value="pear">Груша</option>
<option value="banana">Банан</option>
</select>
Для очистки вводимых данных можно использовать слдедующую стратегию:
slice:=[]string{"apple","pear","banana"}
for _, v := range slice {
if v == r.Form.Get("fruit") {
return true
}
}
return false
Все функции, котоые я показал выше, есть в моем open source проекте для оперирования срезами и картами: https://github.com/astaxie/beeku
Радиокнопки
Если нам нужно узнать пол пользователя, мы можем вопсользоваться радиокнопками, которые будут возвращать 1 для мужчины и 2 для женщины. Однако, какой-нибудь маленький ребенок, прочитав свою первую книгу по HTTP, захочет послать Вам 3. Будет ли готова Ваша программа обработать это исключение? Как Вы увидите, для того, чтобы узнать, послано ли нам значение из нужного диапазона, мы используем тот же метод, что и для выпадающих списков:
<input type="radio" name="gender" value="1">Мужчина
<input type="radio" name="gender" value="2">Женщина
Для проверки мы используем следующий код:
slice:=[]int{1,2}
for _, v := range slice {
if v == r.Form.Get("gender") {
return true
}
}
return false
Чекбоксы
Предположим у нас имеются несколько чекбоксов для получения информации об интересах пользователя, и мы не хотим, чтобы они возвращали непредусмотренные значения.
<input type="checkbox" name="interest" value="football">Футбол
<input type="checkbox" name="interest" value="basketball">Баскетбол
<input type="checkbox" name="interest" value="tennis">Теннис
В этом случае проверка входящих данных немного отличается от того, что было с радиокнопками, так как чекбокс возвращает срез значений:
slice:=[]string{"football","basketball","tennis"}
a:=Slice_diff(r.Form["interest"],slice)
if a == nil{
return true
}
return false
Дата и время
Предположим, Вы хотите, чтобы пользователи вводили дату и время правильно. Для конвертирования лет, месяцев и дней в соответствующие значения типа 'time' в Go есть пакет time. С его помощью можно легко проверить введенную дату.
t := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
fmt.Printf("Go запущен в %s\n", t.Local())
После того, как нам стало известно время, мы можем использовать пакет time для решения еще большего числа задач в зависимости от наших потребностей.
В этом разделе мы обсудили несколько общих способов проверки данных пользовательских форм на стороне сервера. Я надеюсь, что теперь Вы больше понимаете о проверке данных в Go, особенно о том, как использовать регулярные выражения.
Ссылки
- Содержание
- Предыдущий раздел: Работа с формами
- Следующий раздел: Межсайтовый скриптинг