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,http.StatusInternalServerError)
    }
}

这种情况发生在 Chrome、FF、Bravo、Safari 上。

协议是 https。

解决方法

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

关于您的处理程序的一些错误和注意事项。

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

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

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

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

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