英文:
Golang - POST failed (NoSurf CSRF)
问题
我正在使用NoSurf来处理我的Golang代码中的CSRF。这是Trevor Sawler的Golang课程第8.2节的内容。如果有需要,我决定使用Bootstrap 5而不是教程中的Bootstrap 4。我的代码可以在这里找到。要启动Web服务器,我使用go run ./cmd/web/*.go
命令。所以在cmd\web\routes.go
文件中,以下内容适用于localhost:8080/search-availability
页面:
mux.Get("/search-availability", handlers.Repo.Availability)
mux.Post("/search-availability", handlers.Repo.AvailabilityPost)
在pkg\handlers\handlers.go
文件中,我有以下代码:
func (m *Repository) Availability(w http.ResponseWriter, r *http.Request) {
log.Println("Availability")
render.RenderTemplate(w, r, "search-availability.page.tmpl", &models.TemplateData{})
}
func (m *Repository) AvailabilityPost(w http.ResponseWriter, r *http.Request) {
log.Println("Before Write")
w.Write([]byte("Posted to search-availability"))
log.Println("After Write")
}
在pkg\render\render.go
文件中,我有以下代码:
func AddDefaultData(td *models.TemplateData, r *http.Request) *models.TemplateData {
td.CsrfToken = nosurf.Token(r)
return td
}
在pkg\models\templatedata.go
文件中,我有以下代码:
type TemplateData struct {
StringMap map[string]string
IntMap map[string]int
FloatMap map[string]float64
Data map[string]interface{}
CsrfToken string
Flash string
Error string
}
在templates\search-availability.page.tmpl
文件的第13行,我有以下代码:
<input type="text" name="csrf_token" value="{{.CsrfToken}}">
在从localhost:8080/search-availability
页面选择开始和结束日期后,单击Search Availability
按钮总是返回400 Bad Request
错误,如下图所示:
从终端中,我可以看到代码从未进入AvailabilityPost
函数:
2023/03/12 19:06:48 Hit the page
2023/03/12 19:06:48 Availability
2023/03/12 19:06:51 Hit the page
然而,如果我在cmd\web\routes.go
文件中禁用nosurf
,如下所示:
func routes(app *config.AppConfig) http.Handler {
mux := chi.NewRouter()
mux.Use(middleware.Recoverer)
mux.Use(WriteToConsole)
// mux.Use(NoSurf)
mux.Use(SessionLoad)
...
mux.Get("/search-availability", handlers.Repo.Availability)
mux.Post("/search-availability", handlers.Repo.AvailabilityPost)
...
fileServer := http.FileServer(http.Dir("./static/"))
mux.Handle("/static/*", http.StripPrefix("/static", fileServer))
return mux
}
浏览器将显示成功的POST请求:
Posted to search-availability
终端也确认了这一点:
2023/03/12 19:19:46 Hit the page
2023/03/12 19:19:46 Availability
2023/03/12 19:19:48 Hit the page
2023/03/12 19:19:48 Before Write
2023/03/12 19:19:48 After Write
有人能指出我做错了什么吗?我无法像教程中那样成功进行POST请求。这些资料有点过时,但我看不出可能会有问题。
英文:
I am using NoSurf for CSRF in my Golang code. This is from Trevor Sawler's Golang course, section 8.2. If anything, I decide to go with Bootstrap 5 instead the tutorial's Bootstrap 4. My code can be found here. To activate the web server, I use go run ./cmd/web/*.go
. So inside cmd\web\routes.go
, the following are available for the localhost:8080/search-availability
page:
mux.Get("/search-availability", handlers.Repo.Availability)
mux.Post("/search-availability", handlers.Repo.AvailabilityPost)
Inside pkg\handlers\handlers.go
, I have:
func (m *Repository) Availability(w http.ResponseWriter, r *http.Request) {
log.Println("Availability")
render.RenderTemplate(w, r, "search-availability.page.tmpl", &models.TemplateData{})
}
func (m *Repository) AvailabilityPost(w http.ResponseWriter, r *http.Request) {
log.Println("Before Write")
w.Write([]byte("Posted to search-availability"))
log.Println("After Write")
}
Inside pkg\render\render.go
, I have:
func AddDefaultData(td *models.TemplateData, r *http.Request) *models.TemplateData {
td.CsrfToken = nosurf.Token(r)
return td
}
Inside pkg\models\templatedata.go
, I have:
type TemplateData struct {
StringMap map[string]string
IntMap map[string]int
FloatMap map[string]float64
Data map[string]interface{}
CsrfToken string
Flash string
Error string
}
Inside templates\search-availability.page.tmpl
, I have on line 13:
<input type="text" name="csrf_token" value="{{.CsrfToken}}">
After choosing the start and end date from the localhost:8080/search-availability
page, clicking on the Search Availability
button always gets me a 400 Bad Request
as seen below.
From the terminal, I can see that the code never enters AvailabilityPost
:
2023/03/12 19:06:48 Hit the page
2023/03/12 19:06:48 Availability
2023/03/12 19:06:51 Hit the page
However if I disable nosurf
inside cmd\web\routes.go
like this:
func routes(app *config.AppConfig) http.Handler {
mux := chi.NewRouter()
mux.Use(middleware.Recoverer)
mux.Use(WriteToConsole)
// mux.Use(NoSurf)
mux.Use(SessionLoad)
...
mux.Get("/search-availability", handlers.Repo.Availability)
mux.Post("/search-availability", handlers.Repo.AvailabilityPost)
...
fileServer := http.FileServer(http.Dir("./static/"))
mux.Handle("/static/*", http.StripPrefix("/static", fileServer))
return mux
}
The browser shows a successful post:
Posted to search-availability
The terminal also confirms:
2023/03/12 19:19:46 Hit the page
2023/03/12 19:19:46 Availability
2023/03/12 19:19:48 Hit the page
2023/03/12 19:19:48 Before Write
2023/03/12 19:19:48 After Write
Could someone point out what I have done wrong? I am not getting a successful post as seen in the tutorial. The material is a bit dated, but I can't see how it be an issue.
答案1
得分: 2
你在提交表单时没有发送CSRF令牌输入。
要解决这个问题,你可以通过两种方式之一来修复:要么将CSRF输入元素添加到你的表单(date-picker)中,并将其设置为表单的ID,要么将CSRF输入元素移动到表单元素内部。
英文:
You didn't send the CSRF token input on form submit.
To fix this, you can either add the form attribute to your CSRF input element and set it to the ID of your form (date-picker), or move the CSRF input element inside the form element.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论