6

我不能以这种方式从会话中获得价值,它是nil

session := initSession(r)
valWithOutType := session.Values[key]

完整代码:

package main

import (
    "fmt"
    "github.com/gorilla/mux"
    "github.com/gorilla/sessions"
    "log"
    "net/http"
)

func main() {
    rtr := mux.NewRouter()
    rtr.HandleFunc("/setSession", handler1).Methods("GET")
    rtr.HandleFunc("/getSession", handler2).Methods("GET")
    http.Handle("/", rtr)
    log.Println("Listening...")
    http.ListenAndServe(":3000", http.DefaultServeMux)
}

func handler1(w http.ResponseWriter, r *http.Request) {
    SetSessionValue(w, r, "key", "value")
    w.Write([]byte("setSession"))
}

func handler2(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("getSession"))
    value := GetSessionValue(w, r, "key")
    fmt.Println("value from session")
    fmt.Println(value)
}

var authKey = []byte("secret") // Authorization Key

var encKey = []byte("encKey") // Encryption Key

var store = sessions.NewCookieStore(authKey, encKey)

func initSession(r *http.Request) *sessions.Session {
    store.Options = &sessions.Options{
        MaxAge:   3600 * 1, // 1 hour
        HttpOnly: true,
    }
    session, err := store.Get(r, "golang_cookie")
    if err != nil {
        panic(err)
    }

    return session
}

func SetSessionValue(w http.ResponseWriter, r *http.Request, key, value string) {
    session := initSession(r)
    session.Values[key] = value
    fmt.Printf("set session with key %s and value %s\n", key, value)
    session.Save(r, w)
}

func GetSessionValue(w http.ResponseWriter, r *http.Request, key string) string {
    session := initSession(r)
    valWithOutType := session.Values[key]
    fmt.Printf("valWithOutType: %s\n", valWithOutType)
    value, ok := valWithOutType.(string)
    if !ok {
        fmt.Println("cannot get session value by key: " + key)
    }
    return value
}

输出:

myMac ~/forStack/session $ go run ./session.go
2015/01/30 16:47:26 Listening...

首先我打开 urlhttp://localhost:3000/setSession并获得输出:

set session with key key and value value

然后我打开 urlhttp://localhost:3000/getSession并得到输出:

valWithOutType: %!s(<nil>)
cannot get session value by key: key
value from session

为什么valWithOutType是 nil,尽管我将它设置为请求/setSession

更新

我根据@isza 的答案更改了代码,但会话值仍然是nil.

package main

import (
    "fmt"
    "github.com/gorilla/mux"
    "github.com/gorilla/sessions"
    "log"
    "net/http"
)

func main() {
    rtr := mux.NewRouter()
    rtr.HandleFunc("/setSession", handler1).Methods("GET")
    rtr.HandleFunc("/getSession", handler2).Methods("GET")
    http.Handle("/", rtr)
    log.Println("Listening...")
    store.Options = &sessions.Options{
        MaxAge:   3600 * 1, // 1 hour
        HttpOnly: true,
        Path:     "/", // to match all requests
    }
    http.ListenAndServe(":3000", http.DefaultServeMux)

}

func handler1(w http.ResponseWriter, r *http.Request) {
    SetSessionValue(w, r, "key", "value")
    w.Write([]byte("setSession"))
}

func handler2(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("getSession"))
    value := GetSessionValue(w, r, "key")
    fmt.Println("value from session")
    fmt.Println(value)
}

var authKey = []byte("secret") // Authorization Key

var encKey = []byte("encKey") // Encryption Key

var store = sessions.NewCookieStore(authKey, encKey)

func initSession(r *http.Request) *sessions.Session {
    session, err := store.Get(r, "golang_cookie")
    if err != nil {
        panic(err)
    }
    return session
}

func SetSessionValue(w http.ResponseWriter, r *http.Request, key, value string) {
    session := initSession(r)
    session.Values[key] = value
    fmt.Printf("set session with key %s and value %s\n", key, value)
    session.Save(r, w)
}

func GetSessionValue(w http.ResponseWriter, r *http.Request, key string) string {
    session := initSession(r)
    valWithOutType := session.Values[key]
    fmt.Printf("valWithOutType: %s\n", valWithOutType)
    value, ok := valWithOutType.(string)
    if !ok {
        fmt.Println("cannot get session value by key: " + key)
    }
    return value
}
4

4 回答 4

3

What you are probably doing in your init session function with the get method you are restarting the whole session again so every time you do it the session is empty. I did a quick hack around what you wrote to show you where your error is. Please work around this example!

package appSession

import (        
    "net/http"
    "fmt"
    "log"
    "github.com/gorilla/sessions"    
)

var appSession *sessions.Session;

var authKey = []byte("qwer")
var encKey = []byte("asdf")

var store = sessions.NewCookieStore(authKey, encKey)    

func initSession(r *http.Request) *sessions.Session {

    log.Println("session before get", appSession)

    if appSession != nil {    
        return appSession;    
    }

    session, err := store.Get(r, "golang_cookie")
    appSession = session;

    log.Println("session after get", session)
    if err != nil {
        panic(err)
    }
    return session
}

func SetSessionValue(w http.ResponseWriter, r *http.Request, key, value string) {
    session := initSession(r)
    session.Values[key] = value
    fmt.Printf("set session with key %s and value %s\n", key, value)
    session.Save(r, w)
}

func GetSessionValue(w http.ResponseWriter, r *http.Request, key string) string {   
    session := initSession(r)
    valWithOutType := session.Values[key]
    fmt.Printf("valWithOutType: %s\n", valWithOutType)
    value, ok := valWithOutType.(string)
    log.Println("returned value: ", value);

    if !ok {
        fmt.Println("cannot get session value by key: " + key)
    }
    return value
}
于 2015-06-26T17:20:01.837 回答
1

In your initSession() function you change the store options:

store.Options = &sessions.Options{
    MaxAge:   3600 * 1, // 1 hour
    HttpOnly: true,
}

The Options struct also contains an important Path field to which the cookie will apply. If you don't set it, its default value will be the empty string: "". This will most likely cause that the cookie will not be matched with any of your urls/paths, so your existing session will not be found.

Add a path to match all your urls like this:

store.Options = &sessions.Options{
    Path:     "/",      // to match all requests
    MaxAge:   3600 * 1, // 1 hour
    HttpOnly: true,
}

Also you shouldn't change store.Options in each call of initSession() since you call this in each incoming request. Just set this once when you create your store like this:

var store = sessions.NewCookieStore(authKey, encKey)

func init() {
    store.Options = &sessions.Options{
        Path:     "/",      // to match all requests
        MaxAge:   3600 * 1, // 1 hour
        HttpOnly: true,
    }
}
于 2015-01-30T15:08:35.953 回答
1

由于我没有找到答案,我决定不使用 cookie 存储,而是使用 redis 存储进行会话。我在这里找到了完整的工作示例

package main

import (
    "fmt"
    "github.com/aaudis/GoRedisSession"
    "log"
    "net/http"
)

var (
    redis_session *rsess.SessionConnect
)

func main() {
    // Configurable parameters
    rsess.Prefix = "sess:" // session prefix (in Redis)
    rsess.Expire = 1800    // 30 minute session expiration

    // Connecting to Redis and creating storage instance
    temp_sess, err := rsess.New("sid", 0, "127.0.0.1", 6379)
    if err != nil {
        log.Printf("%s", err)
    }

    redis_session = temp_sess // assing to global variable

    http.HandleFunc("/", Root)
    http.HandleFunc("/get", Get)
    http.HandleFunc("/set", Set)
    http.HandleFunc("/des", Des)
    http.ListenAndServe(":8888", nil)
}

func Root(w http.ResponseWriter, r *http.Request) {
    w.Header().Add("Content-Type", "text/html")
    fmt.Fprintf(w, `
        Redis session storage example:<br><br>
        <a href="/set">Store key in session</a><br>
        <a href="/get">Get key value from session</a><br>
        <a href="/des">Destroy session</a>
    `)
}

// Destroy session
func Des(w http.ResponseWriter, r *http.Request) {
    s := redis_session.Session(w, r)
    s.Destroy(w)
    fmt.Fprintf(w, "Session deleted!")
}

// Set variable to session
func Set(w http.ResponseWriter, r *http.Request) {
    s := redis_session.Session(w, r)
    s.Set("UserID", "1000")
    fmt.Fprintf(w, "Setting session variable done!")
}

// Get variable from session
func Get(w http.ResponseWriter, r *http.Request) {
    s := redis_session.Session(w, r)
    fmt.Fprintf(w, "Value %s", s.Get("UserID"))
}
于 2015-01-31T00:56:41.763 回答
0

用你的代码玩了半天,终于发现不行,因为你把加密密钥设置为非法值。

/gorilla/sessions 文档中它说:

加密密钥(如果已设置)必须为 16、24 或 32 字节才能选择 AES-128、AES-192 或 AES-256 模式。

所以既然我相信var encKey = []byte("encKey")根本不符合这个要求。反过来,cookie 并不是一开始就设置的。

请参阅我的代码以供参考。我基本上添加了更多命令行输出并使用了带有重定向的模板:

package main

import (
    "fmt"
    "github.com/gorilla/mux"
    "github.com/gorilla/sessions"
    "html/template"
    "log"
    "net/http"
)

var authKey = []byte("secret") // Authorization Key

//var encKey = []byte("encKey") // Encryption Key

var store sessions.Store

func main() {
    rtr := mux.NewRouter()
    rtr.HandleFunc("/setSession/", handler1).Methods("GET")
    rtr.HandleFunc("/getSession/", handler2).Methods("GET")
    http.Handle("/", rtr)
    store = GetCookieStore()
    log.Println("Listening...")
    http.ListenAndServe(":4000", http.DefaultServeMux)

}

//setting up the cookiestore
func GetCookieStore() sessions.Store {

    //maxAge := 3600 * 1 // 1 hour
    maxAge := 100
    //cookieStore := sessions.NewCookieStore(authKey, encKey)
    cookieStore := sessions.NewCookieStore(authKey)

    cookieStore.Options.HttpOnly = true
    cookieStore.Options.Path = "/" // to match all requests
    cookieStore.MaxAge(maxAge)

    return cookieStore
}

func handler1(w http.ResponseWriter, r *http.Request) {
    t, _ := template.New("foo").Parse(getSessionTemplate)

    SetSessionValue(w, r, "key", "value")
    session := initSession(r)
    fmt.Print("handler1: ")
    fmt.Println(session)

    Value, ok := session.Values["key"].(string)
    if !ok {
        fmt.Println("Type assertion to string failed or session value could not be retrieved.")
    }

    t.Execute(w, Value)

}

func handler2(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("getSession"))
    session := initSession(r)
    fmt.Print("handler2: ")
    fmt.Println(session)
    value := GetSessionValue(w, r, "key")
    fmt.Println("value from session")
    fmt.Println(value)
}

func initSession(r *http.Request) *sessions.Session {
    session, err := store.Get(r, "_golang_cookie")
    if err != nil {
        panic(err)
    }
    return session
}

func SetSessionValue(w http.ResponseWriter, r *http.Request, key, value string) {
    session := initSession(r)
    session.Values[key] = value
    fmt.Printf("set session with key %s and value %s\n", key, value)
    session.Save(r, w)
    fmt.Print("setsession: ")
    fmt.Println(session)
}

func GetSessionValue(w http.ResponseWriter, r *http.Request, key string) string {
    session := initSession(r)
    fmt.Print("getsession: ")
    fmt.Println(session)
    valWithOutType := session.Values[key]
    fmt.Printf("valWithOutType: %s\n", valWithOutType)
    value, ok := valWithOutType.(string)
    if !ok {
        fmt.Println("cannot get session value by key: " + key)
    }

    return value
}

var getSessionTemplate = `
<p><label>Session value set:</label></p>
<p><label>Value: is now: {{.}}</label></p>

<p><a href="/getSession/">Getsession</a></p>`
于 2018-09-20T09:25:32.130 回答