首页 > 解决方案 > Cookie 随机设置

问题描述

我正在尝试设置一个 Cookie,有时它可以工作,有时它不能。没有明显的模式。

func quoteGetHandler(w http.ResponseWriter, req *http.Request) {
    parts := strings.Split(req.URL.Path, "/")
    csrfToken := uniuri.NewLen(32)
    exp, err := strconv.Atoi(os.Getenv("COOKIE_EXPIRE"))  //5
    if err != nil {
        http.Error(w, whereami.WhereAmI()+err.Error(), http.StatusInternalServerError)
    }
    expire := time.Now().Add(time.Duration(exp) * time.Minute)
    cookie := http.Cookie{
        Name:     os.Getenv("COOKIE_NAME"), //csrf_token
        Value:    csrfToken, //string
        Path:     "/",
        Expires:  expire,
        HttpOnly: true,
        Secure:   true,
        MaxAge:   0,
        Domain:   os.Getenv("DOMAIN")} //<--example.com
    http.SetCookie(w, &cookie)
    tmp := htmlTags["quote"]
    tmp.CsrfToken = csrfToken
    if 2 < len(parts) && parts[2] != "" {
        tmp.Param = parts[2]
    }
    htmlTags["quote"] = tmp
    err = tmpl.ExecuteTemplate(w, siteType+"quote", htmlTags["quote"])
    if err != nil {
        http.Error(w, whereami.WhereAmI()+err.Error(), http.StatusInternalServerError)
    }
}

这发生在 Chrome、FF、Bravo、Safari 上。

协议是https。

标签: gocookiessetcookie

解决方案


如果没有可重现的示例,“随机”行为很难调试和推理。

有关您的处理程序的一些错误和注释。

  1. 如果COOKIE_EXPIREenv var 不是整数,您的处理程序会发回错误响应并且不返回http.Error()请注意,在将任何内容写入响应(确实写入响应)后,您无法设置其他标头(包括 cookie )。

  2. 如果COOKIE_EXPIRE是整数但为负或0,则 cookie 过期(expire变量)将指向过去,并导致 cookie 在浏览器中被删除。

  3. 如果 cookie 名称无效(COOKIE_NAMEenv var),则 cookie 可能会被静默丢弃(根据 的文档http.SetCookie())。

  4. 由于您设置Securetrue,请注意 cookie 可能已设置在浏览器中,但当向您的服务器发出不安全 (HTTP) 请求时,它不会被包含(发送)。

  5. 如果执行模板失败(tmpl.ExecuteTemplate()),一些响应可能已经提交,所以你不能发送另一个响应(甚至不能http.Error())。您要么必须执行指向缓冲区的模板,如果成功,则发送它;或直接将其发送到响应中,但如果失败,则无法在之后进行更正(最好的办法是记录错误以供以后检查)。


推荐阅读