简单样例
- 首先调用NewCookieStore初始化一个store,同时传入一个secret key用来对session进行认证。
- 在Handler中,调用store.Get()获取一个已经存在的session或(如果不存在)创建一个新的。
- 设置sesssion.Values中的值,session.Values是map[interface{}]interface{}类型。
- 调用session.Save()将session保存到响应中。
在实际项目中,调用session.Save(r,w)时需要检测返回的错误并处理。
Save()方法必须在写入response之前调用,否则session cookie不会发送到客户端。
var store = sessions.NewCookieStore([]byte("something-very-secret"))
func MyHandler(w http.ResponseWriter, r *http.Request) {
session, err := store.Get(r, "s1")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
fmt.Println(session)
session.Values["name"] = "kingeastensun"
session.Save(r, w)
}
func MultiSessionHandler(w http.ResponseWriter, r *http.Request) {
session1, err := store.Get(r, "s1")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
fmt.Println(session1)
session1.Values["name"] = "kingeastensun"
session2, err := store.Get(r, "s2")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
fmt.Println(session2)
session2.Values["name"] = "kingeastensunyx"
sessions.Save(r, w)
}
func main() {
routes := mux.NewRouter()
routes.HandleFunc("/session", MyHandler)
routes.HandleFunc("/musession", MultiSessionHandler)
http.Handle("/", routes)
http.ListenAndServe(":8080", nil)
}
多session的处理
参见MultiSessionHandler,在保存的时候,调用
sessions.Save(r, w)
就可以同时保存session1和session2。
复杂结构数据
type MPerson struct {
FirstName string
LastName string
Email string
Age int
}
type M map[string]interface{}
func init() {
fmt.Println("init")
gob.Register(&MPerson{})
gob.Register(&M{})
}
var store = sessions.NewCookieStore([]byte("something-very-secret"))
func SetMHandler(w http.ResponseWriter, r *http.Request) {
session, err := store.Get(r, "m")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
ms := MPerson{FirstName: "king", LastName: "eastersun"}
session.Values["ms"] = ms
m := make(map[string]interface{})
m["name"] = "kingeasternsun"
session.Values["m"] = m
err = session.Save(r, w)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
func GetMHandler(w http.ResponseWriter, r *http.Request) {
session, err := store.Get(r, "m")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
ms := session.Values["ms"]
// var person = &MPerson{}
if person, ok := ms.(*MPerson); ok {
fmt.Println(person)
} else {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
m := session.Values['m']
// var mmap = M{}
if mmap, ok := m.(*M); ok {
fmt.Println(mmap)
} else {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
func main() {
// fmt.Println(string(securecookie.GenerateRandomKey(32)))
// fmt.Println(string(securecookie.GenerateRandomKey(32)))
routes := mux.NewRouter()
routes.HandleFunc("/setm", SetMHandler)
routes.HandleFunc("/getm", GetMHandler)
http.Handle("/", routes)
http.ListenAndServe(":8080", nil)
}
设置的时候报错
问题在于
m := make(map[string]interface{})
m["name"] = "kingeasternsun"
map[string]interface{}没有注册到session,在init中仅仅注册了MPersion和M,虽然M的定义方式如下:
type M map[string]interface{}
但是在golang中,这种声明方式,M和map[string]interface{}属于不同类型。
修改SetMHandler如下:
func SetMHandler(w http.ResponseWriter, r *http.Request) {
session, err := store.Get(r, "m")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
ms := MPerson{FirstName: "king", LastName: "eastersun"}
session.Values["ms"] = ms
m := M{}
m = make(map[string]interface{})
m["name"] = "kingeasternsun"
session.Values["m"] = m
err = session.Save(r, w)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
cookie设置成功
获取cookie失败
代码中误将双引号写成了单引号
m := session.Values['m']
m := session.Values["m"]
key的更换
在项目中可能会遇到要更换key的需求,sessions也可以方便的实现
var store = sessions.NewCookieStore(
[]byte("new-authentication-key"),
[]byte("new-encryption-key"),
[]byte("old-authentication-key"),
[]byte("old-encryption-key"),
)
store通过这样的创建方法,新的sessions会通过一个key pair进行创建,旧的sessions则通过老的key pair读取。
对于所有的key pair, encryption key 是可选的,如果为空或省略,则不好进行加密。
后记
之前一直在CSDN上写文章,后面会逐步转换到简书上,还请大家多多支持。