英文:
Go Gorilla session not working when hosting on Apache Web Server
问题
这是我的会话化登录表单的Go代码:
package main
import (
"fmt"
"log"
"net/http"
"github.com/gorilla/context"
"github.com/gorilla/sessions"
)
var store = sessions.NewCookieStore([]byte("super-secret"))
func loginAuthHandler(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
username := r.FormValue("username")
password := r.FormValue("password")
if password == "welcome" && username == "guest" {
session, _ := store.Get(r, "session")
session.Values["authenticated"] = true
err := session.Save(r, w)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
http.Redirect(w, r, "/secret", http.StatusFound)
} else {
fmt.Fprintf(w, "Wrong Login!")
}
}
func secret(w http.ResponseWriter, r *http.Request) {
session, _ := store.Get(r, "session")
if auth, ok := session.Values["authenticated"].(bool); !ok || !auth {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
fmt.Fprintf(w, "The cake is a lie!")
}
func main() {
store.Options = &sessions.Options{
Domain: "localhost",
Path: "/",
MaxAge: 3600 * 8,
HttpOnly: true,
}
http.HandleFunc("/secret", secret)
http.HandleFunc("/loginauth", loginAuthHandler)
http.Handle("/", http.FileServer(http.Dir("public")))
log.Fatal(http.ListenAndServe(":3003", context.ClearHandler(http.DefaultServeMux)))
}
出于某种原因,当我在本地主机上托管服务器时,这段代码可以正常工作,但是当我尝试在我的Digital Ocean Droplet上的Linux Apache Web服务器上托管时,它停止工作。网站甚至可以正确地重定向到secret端点,但是因为cookie从未设置,所以显示了Forbidden消息。是否有一些在Apache上托管时引起这个问题的差异?
这是我在服务器上设置Apache代理的代码,除此之外,我基本上保持了服务器的默认设置。
#go
ProxyPass /go http://localhost:3003
ProxyPassReverse /go http://localhost:3003
请注意,Apache代理配置中的/go
路径应与Go代码中的路径匹配。如果您的Go代码中的路径是/
,则代理配置应为:
ProxyPass / http://localhost:3003
ProxyPassReverse / http://localhost:3003
另外,请确保您的服务器上已安装并启用了适当的模块(如mod_proxy
和mod_proxy_http
),以便Apache能够正确地代理请求到Go服务器。
英文:
Here is the Go code for my sessionized login form
package main
import (
"fmt"
"log"
"net/http"
"github.com/gorilla/context"
"github.com/gorilla/sessions"
)
var store = sessions.NewCookieStore([]byte("super-secret"))
func loginAuthHandler(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
username := r.FormValue("username")
password := r.FormValue("password")
if password == "welcome" && username == "guest" {
session, _ := store.Get(r, "session")
session.Values["authenticated"] = true
err := session.Save(r, w)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
http.Redirect(w, r, "/secret", http.StatusFound)
} else {
fmt.Fprintf(w, "Wrong Login!")
}
}
func secret(w http.ResponseWriter, r *http.Request) {
session, _ := store.Get(r, "session")
if auth, ok := session.Values["authenticated"].(bool); !ok || !auth {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
fmt.Fprintf(w, "The cake is a lie!")
}
func main() {
store.Options = &sessions.Options{
Domain: "localhost",
Path: "/",
MaxAge: 3600 * 8,
HttpOnly: true,
}
http.HandleFunc("/secret", secret)
http.HandleFunc("/loginauth", loginAuthHandler)
http.Handle("/", http.FileServer(http.Dir("public")))
log.Fatal(http.ListenAndServe(":3003", context.ClearHandler(http.DefaultServeMux)))
}
For some reason this works when I host the server locally but when I try hosting it on linux Apache Web Server on my Digital Ocean Droplet it stops working. The website even redirects correctly to the secret endpoint but it shows the Forbidden message because the cookie never gets set. Is there some kind of difference that Hosting on Apache makes that is causing this?
Here is the code I used to setup the proxy on my server for Apache, other than that I've kept the server mostly default.
#go
ProxyPass /go http://localhost:3003
ProxyPassReverse /go http://localhost:3003
答案1
得分: 2
您正在将store.Options.Domain
设置为localhost
。Domain
用于构建会话cookie,这意味着cookie的domain属性
将被设置为localhost
。
由于您的服务器托管在云服务器上的Apache反向代理后面,您将无法使用localhost
URL(例如http://localhost/go
)访问它。这意味着您URL中的域名不会是localhost
,因此cookie将被忽略。有关更多信息,请参见此问题。
快速修复方法是将Domain
设置为空,例如:
store.Options = &sessions.Options{
Path: "/",
MaxAge: 3600 * 8,
HttpOnly: true,
}
注意:如果这样做,cookie将不会在子域上可用(但在测试时可能不是问题)。
英文:
You are setting store.Options.Domain
to localhost
. The Domain
is used when building the session cookie; meaning that the cookies domain attribute
will be set to localhost
.
As you are hosting your server behind an Apache reverse proxy on a cloud server you will not be accessing it with a localhost
URL (e.g. http://localhost/go
). This means that the domain within your URL will not be localhost
and the cookie will effectively be ignored. See this question for more info.
The quick fix is to leave the Domain
unset e.g.
store.Options = &sessions.Options{
Path: "/",
MaxAge: 3600 * 8,
HttpOnly: true,
}
Note: If you do this the cookie will not be available on subdomains (but that si probably not an issue whilst testing).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论