[12-Gin的Cookie,Session] 一 Cookie介绍和使用 扩展阅读:cookie,session,token
1.1 介绍 HTTP 是无状态协议。简单地说,当你浏览了一个页面,然后转到同一个网站的另一个页 面,服务器无法认识到这是同一个浏览器在访问同一个网站。每一次的访问,都是没有任何 关系的。如果我们要实现多个页面之间共享数据的话我们就可以使用 Cookie,Session或Token实 现
cookie 是存储浏览器中的键值对,可以让我们用同一个浏览器访问同一个域名 的时候共享数据
1.2 Gin中Cookie的设置 1 2 3 4 5 6 7 8 c.SetCookie(name, value string , maxAge int , path, domain string , secure,httpOnly bool )
1.3 Gin中Cookie的获取 1 cookie, err := c.Cookie("key值" )
1.4 设置获取案例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package mainimport ( "fmt" "github.com/gin-gonic/gin" ) func main () { r := gin.Default() r.GET("set_cookie" , func (c *gin.Context) { c.SetCookie("name" , "lqz" , 60 , "/" , "" , false , true ) c.SetCookie("age" , "19" , 600 , "" , "" , false , true ) c.String(200 , "cookie设置成功" ) }) r.GET("get_cookie" , func (c *gin.Context) { name, err := c.Cookie("name" ) if err != nil { c.String(200 , "cookie获取打印失败,错误是:%s" ,err) return } fmt.Println("name的cookie值为:" ,name) c.String(200 , "cookie获取打印成功" ) }) r.Run(":8080" ) }
1.5 Cookie登陆认证练习
模拟实现权限验证中间件
有2个路由,login和home
login用于设置cookie
home是访问查看信息的请求
在请求home之前,先跑中间件代码,检验是否存在cookie
访问home,会显示错误,因为权限校验未通过
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 package mainimport ( "github.com/gin-gonic/gin" "net/http" ) func AuthMiddleWare () gin.HandlerFunc { return func (c *gin.Context) { if cookie, err := c.Cookie("login" ); err == nil { if cookie == "yes" { c.Next() } } else { c.JSON(http.StatusUnauthorized, gin.H{"error" : "没有登录" }) c.Abort() } } } func main () { r := gin.Default() r.GET("/login" , func (c *gin.Context) { c.SetCookie("login" , "yes" , 60 , "/" , "" , false , true ) c.String(200 , "Login success!" ) }) r.GET("/home" , AuthMiddleWare(), func (c *gin.Context) { c.JSON(200 , gin.H{"data" : "登陆成功,能访问home" }) }) r.Run(":8080" ) }
二 Session的介绍和使用 2.1 Session介绍 session 是另一种记录客户状态的机制,不同的是 Cookie 保存在客户端浏览器中,而 session 保存在服务器上。
2.2 Session工作流程 当客户端浏览器第一次访问服务器并发送请求时,服务器端会创建一个 session 对象,生成 一个类似于 key,value 的键值对,然后将 value 保存到服务器 将 key(cookie)返回到浏览器(客 户)端。浏览器下次访问时会携带 key(cookie),找到对应的 session(value)。
2.3 Gin中使用 Session Gin 官方没有给我们提供 Session 相关的文档,这个时候我们可以使用第三方的 Session 中间 件来实现
推荐一:gin-contrib/sessions后起之秀
https://github.com/gin-contrib/sessions
推荐二:gorilla/sessions年久失修
https://github.com/gorilla/sessions
2.5 gin-contrib/sessions使用
下载:go get github.com/gin-contrib/sessions
2.5.1 session放在内存中 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 package mainimport ( "fmt" "github.com/gin-contrib/sessions" "github.com/gin-contrib/sessions/cookie" "github.com/gin-gonic/gin" ) func main () { r := gin.Default() store := cookie.NewStore([]byte ("lqzisnb" )) r.Use(sessions.Sessions("sessionid" , store)) r.GET("/set_session" , func (c *gin.Context) { session := sessions.Default(c) session.Options(sessions.Options{MaxAge: 3600 * 6 }) session.Set("username" , "lqz" ) session.Save() c.JSON(200 , gin.H{"msg" : "设置session成功----userrname:lqz" }) }) r.GET("/get_session" , func (c *gin.Context) { session := sessions.Default(c) username := session.Get("username" ) fmt.Println(username) c.JSON(200 , gin.H{"msg" : "获取session成功" }) }) r.Run(":8080" ) }
2.5.2 session放在redis中 如果我们想将 session 数据保存到 redis 中,只要将 session 的存储引擎改成 redis 即可。 使用 redis 作为存储引擎的例子,首先安装 redis 存储引擎的包
go get github.com/gin-contrib/sessions/redis
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 package mainimport ( "fmt" "github.com/gin-contrib/sessions" "github.com/gin-contrib/sessions/redis" "github.com/gin-gonic/gin" ) func main () { r := gin.Default() store, _ := redis.NewStore(10 , "tcp" , "localhost:6379" , "" , []byte ("secret" )) r.Use(sessions.Sessions("sessionid" , store)) r.GET("/set_session" , func (c *gin.Context) { session := sessions.Default(c) session.Options(sessions.Options{MaxAge: 3600 * 6 }) session.Set("username" , "pyy" ) session.Save() c.JSON(200 , gin.H{"msg" : "设置session到reids成功----userrname:pyy" }) }) r.GET("/get_session" , func (c *gin.Context) { session := sessions.Default(c) username := session.Get("username" ) fmt.Println(username) c.JSON(200 , gin.H{"msg" : "获取session成功" }) }) r.Run(":8080" ) }
2.6 gorilla/sessions使用
go get github.com/gorilla/sessions
2.6.1 gin框架使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 package mainimport ( "fmt" "github.com/gin-gonic/gin" "net/http" "github.com/gorilla/sessions" ) var store = sessions.NewCookieStore([]byte ("asdfasdf" ))func main () { r:=gin.New() r.GET("/savesession" , func (context *gin.Context) { session, err := store.Get(context.Request, "session-name" ) if err != nil { context.String(http.StatusInternalServerError,"出错了" ) return } session.Values["name" ] = "lqz" session.Values["age" ] = 18 session.Values[42 ] = 43 session.Save(context.Request, context.Writer) context.String(200 ,"保存session成功" ) }) r.GET("getsession" , func (context *gin.Context) { session, err := store.Get(context.Request, "session-name" ) if err != nil { context.String(http.StatusInternalServerError,"出错了" ) return } name := session.Values["name" ] age := session.Values["age" ] count:=session.Values[42 ] fmt.Println(name) fmt.Println(age) fmt.Println(count) context.String(200 ,"查询成功" ) }) r.Run() }
2.6.2 net/http使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 package mainimport ( "fmt" "net/http" "github.com/gorilla/sessions" ) var store = sessions.NewCookieStore([]byte ("something-very-secret" ))func main () { http.HandleFunc("/save" , SaveSession) http.HandleFunc("/get" , GetSession) err := http.ListenAndServe(":8080" , nil ) if err != nil { fmt.Println("HTTP server failed,err:" , err) return } } func SaveSession (w http.ResponseWriter, r *http.Request) { session, err := store.Get(r, "session-name" ) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } session.Values["foo" ] = "bar" session.Values[42 ] = 43 session.Save(r, w) } func GetSession (w http.ResponseWriter, r *http.Request) { session, err := store.Get(r, "session-name" ) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } foo := session.Values["foo" ] fmt.Println(foo) }
2.6.3 删除session的值 1 2 3 4 5 session.Options.MaxAge = -1 session.Save(r, w) GO 复制 全屏