在 Apache Web 服务器上托管时,Gorilla 会话不起作用。

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

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_proxymod_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设置为localhostDomain用于构建会话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).

huangapple
  • 本文由 发表于 2022年8月9日 04:27:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/73283666.html
匿名

发表评论

匿名网友

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

确定