在Internet Explorer中使用Go和gorilla sessions

huangapple go评论102阅读模式
英文:

Go and gorilla sessions in Internet Explorer

问题

我正在使用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选项中的某个设置或者在cookie中添加除"MaxAge"之外的其他内容,以便IE接受它吗?提前感谢您的帮助。

英文:

I'm making a simple web app using Go, gorilla for sessions and routing, and mustache for templates. I'm having an issue with the login involving, I believe, a problem with IE accepting the cookie. The problem only occurs with Internet Explorer, but otherwise the login works perfectly in Chrome. Here is my code:

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))
}
}

When logging in using IE the user is redirected right back to the login page because the session value "username" is nil, while in Chrome the username is correctly defined and the index page is served. For some reason IE is not accepting the cookie, yet I changed all settings in IE to allow cookies from any site. Do I need to change one of the cookie options or add something to the cookie other than "MaxAge" for IE to accept it? Thanks in advance.

答案1

得分: 3

你可能需要在选项中定义cookie的路径。以下选项结构应该可以解决问题:

session.Options = &sessions.Options{
Path: "/performance",
}

该选项将限制cookie在给定路径上的可用性,对于整个页面使用"/"

请注意,max-age设置不受IE支持:

> [...] Internet Explorer(包括IE8)不尝试支持任何RFC的cookie。
WinINET(IE下面的网络堆栈)基于cookie的预-RFC Netscape草案规范实现。这意味着在任何版本的Internet Explorer中都不支持max-age、版本化cookie等指令。

顺便说一下,会话cookie不需要MaxAge(来自IE关于cookie的手册):

<!-- language: lang-none -->

(expires=date;)
如果在cookie上没有设置过期日期,它将在浏览器关闭时过期。如果设置了过期日期,cookie将在浏览器会话之间保存。如果将过期日期设置为过去,cookie将被删除。使用格林尼治标准时间(GMT)格式指定日期。

这对于所有主要浏览器都适用。

英文:

You probably need to define the cookie's path in your options.
The following options struct should do the trick:

session.Options = &amp;sessions.Options{
Path: &quot;/performance&quot;,
}

Said option limits the cookie's availability to the given path, for the whole page
use &quot;/&quot;.

Note that the max-age setting is not supported by IE:

> [...] Internet Explorer (including IE8) does not attempt to support any RFC for cookies.
WinINET (the network stack below IE) has cookie implementation based on the pre-RFC Netscape draft spec for cookies. This means that directives like max-age, versioned cookies, etc, are not supported in any version of Internet Explorer.

By the way, you don't need a MaxAge for session cookies (from the IE manual on cookies):

<!-- language: lang-none -->

(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.

This should be the case for all major browsers.

答案2

得分: 1

我遇到了一个类似的问题,在IE9上无法正常注销,使用Gorilla sessions(尽管登录正常工作)。

最终我发现IE会缓存我的API端点的响应,并将缓存的(304 NOT MODIFIED)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")
英文:

I had a similar problem where logout would not work on IE9, using Gorilla sessions (although login worked fine).

I eventually discovered that IE was caching the responses to my API endpoints and sending the cached (304 NOT MODIFIED) API responses to the client, even though the cookie values where changing.

Forcing the API endpoints to never be cached fixed the problem:

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

huangapple
  • 本文由 发表于 2013年6月12日 04:57:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/17053699.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定