Session Golang不存在大猩猩会话
使用Gorilla会话处理程序在Golang中持久化会话时遇到问题。在其他堆栈溢出问题(这里:和这里:)中也提出了类似的问题(未解决!)。这是非常可怕的,因为似乎1)不仅仅是我2)目前似乎没有一个解决方案3)Gorilla会话包可能从根本上被破坏 下面是更详细的问题: 我可以在登录时设置会话。但是,在我登录并向后端发出另一个请求后,会话值不会持久化,这意味着我无法提取会话。例如,值['username'](即使这是会话的要点) 因此: A) 登录、编写会话、检索会话。值['usernames'],它工作正常 B) 导航到前端的另一个页面,并向后端发出另一个请求(生成新字符) C) 尝试检索会话。值['username']。是零 以下是用户在后端导航以登录的流程- 首先是会话处理程序:Session Golang不存在大猩猩会话,session,go,gorilla,Session,Go,Gorilla,使用Gorilla会话处理程序在Golang中持久化会话时遇到问题。在其他堆栈溢出问题(这里:和这里:)中也提出了类似的问题(未解决!)。这是非常可怕的,因为似乎1)不仅仅是我2)目前似乎没有一个解决方案3)Gorilla会话包可能从根本上被破坏 下面是更详细的问题: 我可以在登录时设置会话。但是,在我登录并向后端发出另一个请求后,会话值不会持久化,这意味着我无法提取会话。例如,值['username'](即使这是会话的要点) 因此: A) 登录、编写会话、检索会话。值['usernames']
package config
import (
"log"
"net/http"
"github.com/gorilla/sessions"
)
type Options struct {
Path string
Domain string
MaxAge int
Secure bool
HttpOnly bool
}
type Session struct {
ID string
Values map[interface{}]interface{}
Options *Options
IsNew bool
}
type Store interface {
Get(r *http.Request, name string) (*sessions.Session, error)
New(r *http.Request, name string) (*sessions.Session, error)
Save(r *http.Request, w http.ResponseWriter, s *sessions.Session) error
}
var SessionsStore = sessions.NewCookieStore([]byte("secret"))
func init() {
SessionsStore.Options = &sessions.Options{
Domain: "localhost",
Path: "/",
MaxAge: 3600 * 8, // 8 hours
HttpOnly: true,
}
}
func KeyStore() (store Store) {
log.Print("inside KeyStore")
store = SessionsStore
log.Print("Value of store is : ", store)
return store
}
接下来,我将介绍如何从main到每个组件的路由:
主要
以下是路由到每个处理程序的路由包:
package main
import (
"net/http"
"github.com/patientplatypus/gorest/users"
"github.com/patientplatypus/gorest/dungeon_db"
"github.com/patientplatypus/gorest/character"
"github.com/patientplatypus/gorest/createcharacter"
"github.com/gorilla/mux"
)
type Route struct {
Name string
Method string
Pattern string
HandlerFunc http.HandlerFunc
}
type Routes []Route
func NewRouter() *mux.Router {
router := mux.NewRouter().StrictSlash(true)
for _, route := range routes {
router.
Methods(route.Method).
Path(route.Pattern).
Name(route.Name).
Handler(route.HandlerFunc)
}
return router
}
var routes = Routes{
Route{
"ClassType",
"POST",
"/character/class",
character.ClassType,
},
<MORE ROUTES FOLLOWING SAME PATTERN>
}
现在是问题组件。它的工作是在检查用户是否存在后创建一个新字符(sessioncheck是ok的)
因此,我有:
package createcharacter
import (
"encoding/json"
"log"
"net/http"
"github.com/patientplatypus/gorest/config"
)
var Username string
var Checkok bool
func SessionsCheck(w http.ResponseWriter, r *http.Request) (username string, checkok bool) {
store := config.KeyStore()
session, _ := store.Get(r, "cookie-name")
log.Print("inside sessionscheck...what is the value of stuff....")
log.Print("session: ", session)
log.Print("session.Values: ", session.Values)
log.Print("username: ", session.Values["username"])
log.Print("authenticated: ", session.Values["authenticated"])
if session.Values["username"] == nil {
if session.Values["authenticated"] == false {
log.Print("Verboten!")
http.Error(w, "Forbidden", http.StatusForbidden)
return "nil", false
}
}
return session.Values["username"].(string), true
}
func NewCharacter(w http.ResponseWriter, r *http.Request) {
Username, Checkok = SessionsCheck(w, r)
<FUNCTION CONTINUES>
似乎表示用户名和经过身份验证的(true 0xc4200e0a80)存储在session.Values[]映射函数之外。为什么呢
编辑:
所以…我认为我编写config.KeyStore()的方式可能是一个问题,所以我将其改写为以下内容,并在整个项目中保持它:
package config
import (
"github.com/gorilla/sessions"
)
var SessionsStore = sessions.NewCookieStore([]byte("secret"))
func init() {
SessionsStore.Options = &sessions.Options{
Domain: "localhost",
Path: "/",
MaxAge: 3600 * 8, // 8 hours
HttpOnly: true,
}
}
所以现在只要我需要sessionstore,我就调用conf.sessionstore。这似乎是一种我认为可行的规范方法。我仍然有同样的问题。小心:您忽略了CookieStore::Get返回的错误-Get始终返回一个非零会话,但该错误可能不为null(就像在新创建的会话中一样)。因此我只是检查了一下。err有nil,但我真的认为问题在于会话映射不正确(请参阅我的编辑)。如果这是问题所在,我不知道如何解决。我查看了Gorilla提供的示例代码(我不使用会话,因为我认为会话从根本上来说是个坏主意,JWT提供了一种无状态的用户身份验证机制),但是代码似乎与您的代码非常不同。你介意看一下文件吗?他似乎使用完全不同的方法。。。我已经看过代码了。我看不出它与我目前使用的有什么不同。您能指出您在完整注释@AlessandroSantini?@Peterwey中看到的任何可能破坏我代码的差异吗?请注意,您不应该使用两个查询来验证数据库中的用户,您可以在同一个查询中选择用户名和密码,并避免不必要的查询,或者更好的
选择user,其中user=$1和password=$2
,然后DB在查找您的行的同时为您进行检查。这已测试正常,但正如您所看到的,我对会话API的API调用与您的完全不同。这与我的非常相似。唯一的区别似乎是我把东西放在不同的文件中,并使cookies成为一个全局变量。请参阅上面我的编辑。是的,我确实错过了编辑,因为我在Atom中:)不过,文件的数量并不是真正的问题。Gorilla会话工作正常,应用程序的流程中一定有问题。很难在本地复制您的环境。我认为这是一个问题。这意味着将会话cookie作为全局变量存在问题。如果我不这样做,这意味着我的所有函数必须在一个文件中(这是不可能的,因为我在整个项目中轮询cookies)。这不是一个概括的解决方案!!!彼得,我试着把这个系统分成三个不同的文件,它工作得完美无缺。我建议你再努力一点。不再研究这个问题了。
package main
import (
"fmt"
"log"
"net/http"
"time"
"github.com/gorilla/mux"
"github.com/gorilla/sessions"
)
const appCookie = "myappcookies"
var cookies *sessions.CookieStore
func Login(w http.ResponseWriter, r *http.Request) {
//
// For the sake of simplicity, I am using a global here.
// You should be using a context.Context instead!
session, err := cookies.Get(r, appCookie)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
log.Println(err)
return
}
session.Values["userName"] = "StackOverflow"
session.Save(r, w)
}
func Session(w http.ResponseWriter, r *http.Request) {
session, err := cookies.Get(r, appCookie)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
log.Println(err)
return
}
w.Write([]byte(fmt.Sprintf("Objects in session: %d\n", len(session.Values))))
for k, v := range session.Values {
w.Write([]byte(fmt.Sprintf("Key=%v, Value=%v\n", k, v)))
}
}
func main() {
cookies = sessions.NewCookieStore([]byte("mysuperdupersecret"))
router := mux.NewRouter()
router.Path("/login").Methods(http.MethodPost).HandlerFunc(Login)
router.Path("/session").Methods(http.MethodGet).HandlerFunc(Session)
server := &http.Server{
Handler: router,
Addr: ":8000",
// Good practice: enforce timeouts for servers you create!
WriteTimeout: 15 * time.Second,
ReadTimeout: 15 * time.Second,
}
log.Fatal(server.ListenAndServe())
}
2017/10/15 15:08:56 inside KeyStore
2017/10/15 15:08:56 Value of store is : &{[0xc42010c000] 0xc42007d5f0}
2017/10/15 15:08:56 inside sessionscheck...what is the value of stuff....
2017/10/15 15:08:56 session: &{ map[] 0xc4201316b0 true 0xc4200e0a80 cookie-name}
2017/10/15 15:08:56 session.Values: map[]
2017/10/15 15:08:56 username: <nil>
2017/10/15 15:08:56 authenticated: <nil>
2017/10/15 15:08:56 http: panic serving [::1]:53668: interface conversion: interface {} is nil, not string
goroutine 13 [running]:
net/http.(*conn).serve.func1(0xc42015c5a0)
/usr/local/opt/go/libexec/src/net/http/server.go:1697 +0xd0
panic(0x133bcc0, 0xc420061f00)
/usr/local/opt/go/libexec/src/runtime/panic.go:491 +0x283
github.com/patientplatypus/gorest/createcharacter.SessionsCheck(0x1540d00, 0xc42010a540, 0xc42014ea00, 0xc42011ab00, 0x3, 0xc420001680)
/Users/patientplatypus/Documents/golang/src/github.com/patientplatypus/gorest/createcharacter/charactercontroller.go:31 +0x5c9
github.com/patientplatypus/gorest/createcharacter.NewCharacter(0x1540d00, 0xc42010a540, 0xc42014ea00)
/Users/patientplatypus/Documents/golang/src/github.com/patientplatypus/gorest/createcharacter/charactercontroller.go:35 +0x5a
net/http.HandlerFunc.ServeHTTP(0x13b8690, 0x1540d00, 0xc42010a540, 0xc42014ea00)
/usr/local/opt/go/libexec/src/net/http/server.go:1918 +0x44
github.com/gorilla/mux.(*Router).ServeHTTP(0xc420066360, 0x1540d00, 0xc42010a540, 0xc42014ea00)
/Users/patientplatypus/Documents/golang/src/github.com/gorilla/mux/mux.go:133 +0xed
github.com/gorilla/handlers.(*cors).ServeHTTP(0xc42010c7e0, 0x1540d00, 0xc42010a540, 0xc42014e800)
/Users/patientplatypus/Documents/golang/src/github.com/gorilla/handlers/cors.go:118 +0x5c8
net/http.serverHandler.ServeHTTP(0xc42014a000, 0x1540d00, 0xc42010a540, 0xc42014e800)
/usr/local/opt/go/libexec/src/net/http/server.go:2619 +0xb4
net/http.(*conn).serve(0xc42015c5a0, 0x1541240, 0xc420061dc0)
/usr/local/opt/go/libexec/src/net/http/server.go:1801 +0x71d
created by net/http.(*Server).Serve
/usr/local/opt/go/libexec/src/net/http/server.go:2720 +0x288
2017/10/15 15:08:56 session: &{ map[] 0xc4201316b0 true 0xc4200e0a80 cookie-name}
2017/10/15 15:08:56 session.Values: map[]
package config
import (
"github.com/gorilla/sessions"
)
var SessionsStore = sessions.NewCookieStore([]byte("secret"))
func init() {
SessionsStore.Options = &sessions.Options{
Domain: "localhost",
Path: "/",
MaxAge: 3600 * 8, // 8 hours
HttpOnly: true,
}
}
package main
import (
"fmt"
"log"
"net/http"
"time"
"github.com/gorilla/mux"
"github.com/gorilla/sessions"
)
const appCookie = "myappcookies"
var cookies *sessions.CookieStore
func Login(w http.ResponseWriter, r *http.Request) {
//
// For the sake of simplicity, I am using a global here.
// You should be using a context.Context instead!
session, err := cookies.Get(r, appCookie)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
log.Println(err)
return
}
session.Values["userName"] = "StackOverflow"
session.Save(r, w)
}
func Session(w http.ResponseWriter, r *http.Request) {
session, err := cookies.Get(r, appCookie)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
log.Println(err)
return
}
w.Write([]byte(fmt.Sprintf("Objects in session: %d\n", len(session.Values))))
for k, v := range session.Values {
w.Write([]byte(fmt.Sprintf("Key=%v, Value=%v\n", k, v)))
}
}
func main() {
cookies = sessions.NewCookieStore([]byte("mysuperdupersecret"))
router := mux.NewRouter()
router.Path("/login").Methods(http.MethodPost).HandlerFunc(Login)
router.Path("/session").Methods(http.MethodGet).HandlerFunc(Session)
server := &http.Server{
Handler: router,
Addr: ":8000",
// Good practice: enforce timeouts for servers you create!
WriteTimeout: 15 * time.Second,
ReadTimeout: 15 * time.Second,
}
log.Fatal(server.ListenAndServe())
}