问题
I cannot get value from session this way, it is nil
:
session := initSession(r)
valWithOutType := session.Values[key]
Full code:
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
}
Output:
myMac ~/forStack/session $ go run ./session.go
2015/01/30 16:47:26 Listening...
First I open url http://localhost:3000/setSession
and get output:
set session with key key and value value
Then I open url http://localhost:3000/getSession
and get output:
valWithOutType: %!s(<nil>)
cannot get session value by key: key
value from session
Why valWithOutType
is nil, although I set it requesting /setSession
?
Update
I changed code according to @isza answer, but session value is still 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
}
回答1:
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
}
回答2:
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,
}
}
回答3:
As I have not found answer I decided not to use cookie store but use redis store for sessions. And I found full working example here
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"))
}
回答4:
I played with your code for a long time and finally found out that it does not work, because you set the encryption key to an illegal value.
In the /gorilla/sessions documentation it says:
The encryption key, if set, must be either 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256 modes.
So since I believe that var encKey = []byte("encKey")
simply does not follow this requirement. In turn, the cookie is not set in the first place.
See my code for reference. I basically added some more command line output and used a template with a redirect:
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>`
来源:https://stackoverflow.com/questions/28237806/cannot-get-gorilla-session-value-by-key