我想在Go Web应用程序中实现CSRF预防。用户未登录,但他们确实填写了表格并付款(通过Stripe Checkout)。

发布内容会在 session 变量(cookie)中设置 key ,以便他们以后可以编辑已发布的内容,并且电子邮件中的URL允许他们在cookie过期后返回,并在需要时再次进行编辑。

从我所看到的,我可以将https://code.google.com/p/xsrftoken/与“双重提交的cookie”方法结合使用,以通过以下方式实现CSRF预防:

  • 针对任意用户ID(通过go-uuid的uuid.V4())生成CSRF token ,如下所示:
    if session.Values["id"] == "" {
    session.Values["id"] = uuid.NewV4()
    }
    
    csrfToken := xsrftoken.Generate(csrfKey, session.Values["id"], "/listing/new/post")
    
  • ...并将其存储在 session 中,并将其呈现在模板的隐藏字段中:
    session.Values["csrfToken"] = csrfToken
    ...
    <input type="hidden" id="_csrf" value={{ .csrfToken }}>
    
  • 当用户提交表单时,我需要获取生成的ID,确认表单中提交的csrfToken与 session 中的ojit_code相匹配,如果是,请使用xsrf软件包对其进行验证以确认它尚未过期:
    userID := session.Values["id"]
    
    if session.Values["csrfToken"] != r.PostFormValue("csrfToken") {
    http.Redirect(w, r, "/listing/new", 400)
    }
    
    if !xsrftoken.Valid(session.Values["csrfToken"], csrfKey, userID, "/listing/new/post") {
    http.Redirect(w, r, "/listing/new", 400)
    }
    

  • 我的相关问题是:
  • 每次呈现表单时,我都应该生成一个新 token 吗?还是在单个用户 session 中重新使用未过期的 token 是否可以接受? 更新:根据this answer,我应该仅在每个 session 中生成一个新 token (即,同一用户以相同的形式获取相同的 token ,直到 token 过期)
  • 给定更新的问题,我如何处理用户请求表单然后提交表单之间创建的 token 到期的情况? (也许还剩10分钟,他们又按了Alt + Tab键了一段时间)将它们重定向回表单(当然,是重新填充的!)并生成新的 session ID + CSRF token ?
  • 是否有其他方法可以做到这一点? Coding Horror指示SO为发送给客户端的每个HTML表单生成唯一的 key 吗?考虑到在生成新 key 时它需要一个userID,我将如何使用xsrf软件包沿这条路线走下去?
  • 我还忽略了什么?
  • 最佳答案



    经常重新生成 token 和 session ID是一个好主意。给定持久的攻击者和可行的进入媒介,攻击者获得两者都只是时间问题。但是,如果在攻击者能够破解当前标识符之前,两个标识符中的至少一个重新生成,则没有问题。



    如果您想给客户大量时间填写表格,则可以通过AJAX更新cookie和CSRF token 。



    token 与需要身份验证的特定操作的绑定(bind)越紧密,您所拥有的控制就越精细。如果您可以唯一地标识应用程序中的每种表单,那么我就说吧。

    关于security - Go Web应用程序中的CSRF,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19129985/

    10-16 12:36