简体   繁体   English

Gorilla CSRF - 禁止 - CSRF 令牌无效 - 当有两个 forms 时失败

[英]Gorilla CSRF - Forbidden - CSRF token invalid - fails when there are two forms

I'm adding in CSRF token validation and I'm running into a problem where I have two forms on a page and one of them will submit successfully and the other will not.我正在添加 CSRF 令牌验证,我遇到了一个问题,我在一个页面上有两个 forms,其中一个将成功提交,另一个不会。 I'm not doing AJAX requests, I'm simply using hidden input fields.我不是在做 AJAX 请求,我只是在使用隐藏的输入字段。 If I submit the form when it is the only one on the page, it submits without issue.如果我在页面上只有表单时提交表单,则它会毫无问题地提交。 If I submit it on a page with more than one form, it fails.如果我在包含多个表单的页面上提交它,它会失败。

Below is the template code for my two forms下面是我的两个 forms 的模板代码

{{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>

And this is what the generated HTML looks like.这就是生成的 HTML 的样子。 Both appear to be valid.两者似乎都是有效的。

在此处输入图像描述

When I click the "Logout" button though, I get the Forbidden - CSRF token invalid error, but clicking the create input value in the second form always works.但是,当我单击“注销”按钮时,我得到了Forbidden - CSRF token invalid错误,但是单击第二种形式的创建输入值总是有效的。

The logout button is correctly validated when I attempt to use it on the home page which is "/admin/" but it does not work on any of the other pages "/admin/snippet/:id" or "/admin/snippet/create".当我尝试在主页“/admin/”上使用它时,注销按钮得到了正确验证,但它在任何其他页面“/admin/snippet/:id”或“/admin/snippet/”上都不起作用创造”。 The Logout button is part of a base template, so it appears on every page, so there shouldn't be anything different in how it appears on any page.注销按钮是基本模板的一部分,因此它出现在每个页面上,因此它在任何页面上的显示方式应该没有什么不同。

I've read other SO posts about multiple forms & CSRF tokens on a page and I understand there should be no issue with multiple forms with the same information as long as you have each one in it's own form, it should be fine.我已经在页面上阅读了有关多个 forms 和 CSRF 令牌的其他 SO 帖子,并且我知道多个具有相同信息的 forms 应该没有问题,只要您每个都有自己的形式,应该没问题。 So I am not sure where I am going wrong.所以我不确定我哪里出错了。

I found the issue.我发现了这个问题。 Currently the way that gorilla/csrf works, it does not like creating the masked token from one path and then sending that token off to another path.目前 gorilla/csrf 的工作方式,它不喜欢从一个路径创建掩码令牌,然后将该令牌发送到另一条路径。 So in my situation, going from /admin/snippet/create to /admin/logout threw an error because it was expecting the path for the token to be /admin/snippet/<something> and so it threw an error.因此,在我的情况下,从/admin/snippet/create/admin/logout会引发错误,因为它期望令牌的路径为/admin/snippet/<something> ,因此会引发错误。

This issue has been addressed in this PR: https://github.com/gorilla/csrf/pull/147 and essentially the solution is to set the default path yourself to something which all of your routes will contain, so in my case that was /admin此问题已在此 PR 中得到解决: https://github.com/gorilla/csrf/pull/147基本上解决方案是自己将默认路径设置为所有路由都将包含的内容,所以在我的情况下是/admin

This is what my CSRF declaration looks like now in main.go这就是我的 CSRF 声明现在在main.go中的样子

var csrfMiddleWare = csrf.Protect(
        []byte("<put your 32 character key here>"),
        csrf.Path("/admin"),
        csrf.Secure(false),
)

A note, if you had this issue and then apply this fix and it doesn't resolve the problem, trying testing in a separate browser as there may be some caching issues.请注意,如果您遇到此问题,然后应用此修复程序并不能解决问题,请尝试在单独的浏览器中进行测试,因为可能存在一些缓存问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM