安全核验
之前写的代码中,没有对路径做任何验证,这是极度危险的,用户可以访问任意路径,极大可能触发或被有心利用漏洞。
可以通过函数 regexp.MustCompile 对自定义的正则表达式编译(编译失败会 panic),再使用该规则对每一次请求的路径进行核验。
所有改动如下:
go
// 添加正则表达式核验路径
var validPath = regexp.MustCompile("^/(edit|save|view)/([a-zA-Z0-9]+)$")
// 使用正则表达式来验证请求路径的有效性,并提取页面标题。
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 // 标题是正则表达式的第二个子表达式。
/* 正则表达式中,用圆括号 () 包裹的部分叫做「捕获组」(Capturing Group),它会把匹配到的内容单独提取出来。
在这个正则表达式中,第二个捕获组 `([a-zA-Z0-9]+)` 用来匹配页面标题,并且这个标题只能包含字母和数字。
通过 `m[2]` 可以获取到这个捕获组匹配到的内容,也就是页面标题。*/
}
// 修改每个处理器的标题提取部分,直接使用这个函数即可
// 例如
func viewHandler(w http.ResponseWriter, r *http.Request) {
// title := r.URL.Path[len("/view/"):]
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)
}