【发布时间】:2021-04-09 12:35:59
【问题描述】:
我正在添加 CSRF 令牌验证,我遇到了一个问题,我在一个页面上有两个表单,其中一个会成功提交,而另一个不会。我不是在做 AJAX 请求,我只是在使用隐藏的输入字段。如果我在页面上只有表单时提交表单,则它会毫无问题地提交。如果我在包含多个表单的页面上提交它,它会失败。
下面是我的两个表单的模板代码
{{if .IsAuthenticated}}
<form action='/admin/logout' method='POST'>
<button>Logout</button>
{{.CsrfField}}
</form>
{{end}}
<form action='/admin/stuff/create' method='POST'>
{{with .Form}}
<div>
<label>Title:</label>
<input type='text' name='title' value='{{.Get "title"}}'>
</div>
<div>
<input type='submit' value='Publish stuff'>
</div>
{{end}}
{{.CsrfField}}
</form>
这就是生成的 HTML 的样子。两者似乎都有效。
当我点击“注销”按钮时,我得到了Forbidden - CSRF token invalid 错误,但点击第二种形式的创建输入值总是有效的。
当我尝试在主页“/admin/”上使用它时,注销按钮得到了正确验证,但它在任何其他页面“/admin/sn-p/:id”或“上都不起作用/admin/sn-p/创建”。注销按钮是基本模板的一部分,因此它出现在每个页面上,因此它在任何页面上的显示方式应该没有什么不同。
我在一个页面上阅读了关于多个表单和 CSRF 令牌的其他 SO 帖子,并且我知道具有相同信息的多个表单应该没有问题,只要每个表单都有自己的表单,应该没问题.所以我不确定我哪里出错了。
【问题讨论】:
-
This library generates unique-per-request token。每个请求都会屏蔽令牌以减轻BREACH attack 的影响。您不能多次使用同一个令牌。你需要一个 unique-per-session 令牌,这个库不能这样做。
-
是的,每个请求都是唯一的,但是为什么完全相同的令牌会以不同的形式工作呢?是同一个会话,所以发送到后端的时候应该能找到令牌吧?
-
另外,我不确定我是否在上面明确了我的问题,当我从仅包含单个 CSRF 令牌的页面点击注销按钮时,仍然会发生此错误。它仅在我在“主页”页面上时有效,即“/admin/”
标签: forms go csrf gorilla csrf-token