在Internet Explorer中使用Go和Gorilla会话

4

我正在使用 Go、gorilla 会话和路由以及 mustache 模板制作一个简单的 Web 应用程序。在登录期间遇到了问题,我认为这是 IE 接受 cookie 的问题。这个问题只出现在 Internet Explorer 中,但是在 Chrome 中登录完全正常。以下是我的代码:

func main() {
    r := mux.NewRouter()
    r.HandleFunc("/performance", Index)
    r.HandleFunc("/performance/login", Login)
    log.Fatal(http.ListenAndServe(":5901", r))
}

func Index(w http.ResponseWriter, r *http.Request) {
    session, _ := store.Get(r, "performance")
    if session.Values["username"] == nil {
        http.Redirect(w, r, "/performance/login", http.StatusSeeOther)
    }
    dict := session.Values
    fmt.Fprintf(w, mustache.RenderFileInLayout("templates/index.html", "templates/basepage.html", dict))
}

func Login(w http.ResponseWriter, r *http.Request) {
    if r.Method == "POST" {
        results := 0
        r.ParseForm()
        u := r.FormValue("username")
        pass := r.FormValue("password")
        p := PassEncrypt(pass)
        q := map[string]string{}
        rows, err := db.Query("SELECT username, name, title FROM user WHERE (username=$1) AND (password=$2)", u, p)
        if err != nil {
            log.Fatal(err)
        }
        for rows.Next() {
            var username string
            var name string
            var title string
            if err := rows.Scan(&username, &name, &title); err != nil {
                log.Fatal(err)
            }
            q["username"] = username
            q["name"] = name
            q["title"] = title
            results++
        }
        if results > 0 {
            session, _ := store.Get(r, "performance")
            session.Options = &sessions.Options{
                MaxAge: 900,
            }
            session.Values["username"] = q["username"]
            session.Values["name"] = q["name"]
            session.Values["title"] = q["title"]
            session.Save(r, w)
            http.Redirect(w, r, "/performance", http.StatusSeeOther)
        } else {
            http.Redirect(w, r, "/performance/login", http.StatusSeeOther)
        }
    } else {
        fmt.Fprintf(w, mustache.RenderFileInLayout("templates/login.html", "templates/basepage.html", nil))
    }
}

使用IE登录时,由于会话值“username”为nil,用户被重定向回登录页面,而在Chrome中,用户名已正确定义并提供了索引页面。出于某种原因,IE不接受cookie,尽管我已更改了IE中的所有设置,以允许来自任何站点的cookie。我需要更改cookie选项中的某个选项或添加除“MaxAge”之外的其他内容到cookie中,以便IE接受它吗?谢谢。


这会很好,如果您缩短您的代码,以便它容易再现。我这次为您做到了(或多或少) - nemo
1
抱歉,我担心发布的内容太少 - 这是我在SO上的第一个问题。谢谢你的提示。 - h2ounderthebridge
2个回答

3
您可能需要在选项中定义cookie的路径。以下选项结构应该能解决问题:
session.Options = &sessions.Options{
    Path: "/performance",
}

该选项限制了cookie在给定路径下的可用性,对于整个页面使用"/"
请注意,max-age设置在IE中不被支持

[...]Internet Explorer(包括IE8)不尝试支持任何关于cookies的RFC规范。WinINET(IE下方的网络堆栈)采用基于早期Netscape草案规范的cookie实现。这意味着像max-age、带版本的cookies等指令在任何版本的Internet Explorer中都不受支持。

顺便说一句,会话cookie不需要MaxAge(来自IE cookies手册):
(expires=date;)
    If you set no expiration date on a cookie, it expires when the browser 
    closes. If you set an expiration date, the cookie is saved across browser 
    sessions. If you set an expiration date in the past, the cookie is deleted. 
    Use Greenwich Mean Time (GMT) format to specify the date.

这应该适用于所有主要的浏览器。


这看起来像是成功了。我甚至没有想过它,因为我尝试了登录,然后查看了IE开发工具中的cookie,并认为Path设置正确。不过,显式地将Path添加到选项中似乎起作用了。感谢您的帮助! - h2ounderthebridge

1

我曾经遇到一个类似的问题,即在使用Gorilla会话时,IE9无法正常注销(尽管登录功能正常)。

最终我发现,IE缓存了我的API端点的响应,并将缓存的(304未修改)API响应发送给客户端,尽管cookie值已更改。

强制API端点永不缓存解决了这个问题:

w.Header().Set("Expires", "Tue, 03 Jul 2001 06:00 GMT")
w.Header().Set("Last-Modified", "{now} GMT")
w.Header().Set("Cache-Control", "max-age=0, no-cache, must-revalidate, proxy-revalidate")

谢谢,这对我非常有帮助。添加这些行代码强制IE像其他浏览器一样发送新的数据请求。 - Owen Ivory

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接