Как вы могли заметить, у нашего приложения есть серьезный недостаток безопасности: пользователь может предоставить произвольный путь для чтения/записи на сервере. Для снижения вероятности некорректного действия мы можем написать функцию для проверки заголовка с помощью регулярного выражения.
Сначала добавьте "regexp"
в список import
. Затем мы можем создать глобальную переменную для хранения нашей проверочного выражения:
var validPath = regexp.MustCompile(
"^/(edit|save|view)/([a-zA-Z0-9]+)$")
Функция regexp.MustCompile
проанализирует и скомпилирует регулярное выражение и вернет regexp.Regexp
. MustCompile
отличается от Compile
тем, что он вызывает panic, если компиляция выражения не удается, а Compile
возвращает error
в качестве второго параметра.
Теперь давайте напишем функцию, которая использует validPath
выражение для проверки пути и извлечения заголовка страницы:
func getTitle(w http.ResponseWriter,
r *http.Request) (string, error) {
m := validPath.FindStringSubmatch(r.URL.Path)
if m == nil {
http.NotFound(w, r)
return "", errors.New("Invalid Page Title")
}
return m[2], nil // title это второе подвыражение.
}
Если заголовок действителен, он будет возвращен вместе с ошибкой со значением nil
. Если заголовок недействителен, функция напишет ошибку «404 Not Found» для HTTP-соединения и вернет ошибку обработчику. Чтобы создать новую ошибку, мы должны импортировать errors
пакет.
Давайте поместим вызов getTitle
в каждом из обработчиков:
func viewHandler(w http.ResponseWriter, r *http.Request) {
title, err := getTitle(w, r)
if err != nil {
return
}
p, err := loadPage(title)
if err != nil {
http.Redirect(w, r,
"/edit/"+title, http.StatusFound)
return
}
renderTemplate(w, "view", p)
}
func editHandler(w http.ResponseWriter, r *http.Request) {
title, err := getTitle(w, r)
if err != nil {
return
}
p, err := loadPage(title)
if err != nil {
p = &Page{Title: title}
}
renderTemplate(w, "edit", p)
}
func saveHandler(w http.ResponseWriter, r *http.Request) {
title, err := getTitle(w, r)
if err != nil {
return
}
body := r.FormValue("body")
p := &Page{Title: title, Body: []byte(body)}
err = p.save()
if err != nil {
http.Error(w, err.Error(),
http.StatusInternalServerError)
return
}
http.Redirect(w, r,
"/view/"+title, http.StatusFound)
}
Читайте также:
- Веб-приложение на Go: использование net/http для обслуживания вики-страниц
- Веб-приложение на Go: редактирование страниц, пакет html/template
- Веб-приложение на Go: обработка несуществующих страниц, сохранение страниц
Комментариев нет:
Отправить комментарий