Golang – POST请求失败(NoSurf CSRF)

huangapple go评论84阅读模式
英文:

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错误,如下图所示:

Golang – POST请求失败(NoSurf CSRF)

从终端中,我可以看到代码从未进入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(&quot;/search-availability&quot;, handlers.Repo.Availability)
mux.Post(&quot;/search-availability&quot;, handlers.Repo.AvailabilityPost)

Inside pkg\handlers\handlers.go, I have:

func (m *Repository) Availability(w http.ResponseWriter, r *http.Request) {
	log.Println(&quot;Availability&quot;)
	render.RenderTemplate(w, r, &quot;search-availability.page.tmpl&quot;, &amp;models.TemplateData{})
}

func (m *Repository) AvailabilityPost(w http.ResponseWriter, r *http.Request) {
	log.Println(&quot;Before Write&quot;)
	w.Write([]byte(&quot;Posted to search-availability&quot;))
	log.Println(&quot;After Write&quot;)
}

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:

&lt;input type=&quot;text&quot; name=&quot;csrf_token&quot; value=&quot;{{.CsrfToken}}&quot;&gt;

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.

Golang – POST请求失败(NoSurf CSRF)

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(&quot;/search-availability&quot;, handlers.Repo.Availability)
	mux.Post(&quot;/search-availability&quot;, handlers.Repo.AvailabilityPost)
	...

	fileServer := http.FileServer(http.Dir(&quot;./static/&quot;))
	mux.Handle(&quot;/static/*&quot;, http.StripPrefix(&quot;/static&quot;, 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.

huangapple
  • 本文由 发表于 2023年3月12日 20:25:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/75713085.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定