• 12Gin的Cookie,Session.md


    一 Cookie介绍和使用

    扩展阅读:cookie,session,token

    1.1 介绍

    HTTP 是无状态协议。简单地说,当你浏览了一个页面,然后转到同一个网站的另一个页 面,服务器无法认识到这是同一个浏览器在访问同一个网站。每一次的访问,都是没有任何 关系的。如果我们要实现多个页面之间共享数据的话我们就可以使用 Cookie,Session或Token实 现

    cookie 是存储浏览器中的键值对,可以让我们用同一个浏览器访问同一个域名 的时候共享数据

    1.2 Gin中Cookie的设置

    c.SetCookie(name, value string, maxAge int, path, domain string, secure,httpOnly bool)
    // name:cookie的key值
    // value:cookie的value值
    // maxAge:过期时间,如果只想设置Cookie的保存路径而不想设置存活时间,可以设置为 nil
    // path:cookie 的路径
    // domain:cookie 的路径 Domain 作用域 本地调试配置成 localhost , 正式上线配置成域名
    // secure:当 secure 值为 true 时,cookie 在 HTTP 中是无效,在 HTTPS 中 才有效
    // httpOnly:是微软对 COOKIE 做的扩展。如果在 COOKIE 中设置了"httpOnly"属性,则通过程序(JS 脚本、applet 等)将无法读取到 COOKIE 信息,防止 XSS 攻击产生
    

    1.3 Gin中Cookie的获取

    cookie, err := c.Cookie("key值")
    

    1.4 设置获取案例

    package main
    
    import (
       "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,会显示错误,因为权限校验未通过
    package main
    
    import (
    	"github.com/gin-gonic/gin"
    	"net/http"
    )
    
    func AuthMiddleWare() gin.HandlerFunc {
    	return func(c *gin.Context) {
    		// 获取客户端cookie并校验
    		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放在内存中

    package main
    
    import (
    	"fmt"
    	"github.com/gin-contrib/sessions"
    	"github.com/gin-contrib/sessions/cookie"
    	"github.com/gin-gonic/gin"
    )
    
    func main() {
    	r := gin.Default()
    	// 创建基于 cookie 的存储引擎,lqzisnb 参数是用于加密的密钥
    	store := cookie.NewStore([]byte("lqzisnb"))
    	// 设置 session 中间件,参数 sessionid,指的是 session 的名字,也是 cookie 的名字
    	//store是前面创建的存储引擎,我们可以替换成其他存储引擎
    	r.Use(sessions.Sessions("sessionid", store))
    	r.GET("/set_session", func(c *gin.Context) {
    		//初始化 session 对象
    		session := sessions.Default(c) //设置过期时间
    		// 过期时间6h
    		session.Options(sessions.Options{MaxAge: 3600 * 6})
    		//设置 Session
    		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)
    		// 通过 session.Get 读取 session 值
    		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

    package main
    
    import (
    	"fmt"
    	"github.com/gin-contrib/sessions"
    	"github.com/gin-contrib/sessions/redis"
    	"github.com/gin-gonic/gin"
    )
    
    func main() {
    	r := gin.Default()
    	// 初始化基于 redis 的存储引擎
    	// size:redis 最大的空闲连接数
    	//network: 数通信协议tcp或者udp
    	//address:redis 地址, 格式,host:port
    	//password:redis密码
    	//最后一个参数:session 加密密钥
    	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
    		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)
    		// 通过 session.Get 读取 session 值
    		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框架使用

    package main
    
    import (
       "fmt"
       "github.com/gin-gonic/gin"
       "net/http"
    
       "github.com/gorilla/sessions"
    )
    
    // 初始化一个cookie存储对象
    // something-very-secret应该是一个你自己的密匙,只要不被别人知道就行
    var store = sessions.NewCookieStore([]byte("asdfasdf"))
    
    func main() {
       r:=gin.New()
       r.GET("/savesession", func(context *gin.Context) {
          // Get a session. We're ignoring the error resulted from decoding an
          // existing session: Get() always returns a session, even if empty.
          session, err := store.Get(context.Request, "session-name")
          if err != nil {
             context.String(http.StatusInternalServerError,"出错了")
             return
          }
    
          // 在session中存储值
          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使用

    package main
    
    import (
        "fmt"
        "net/http"
    
        "github.com/gorilla/sessions"
    )
    
    // 初始化一个cookie存储对象
    // something-very-secret应该是一个你自己的密匙,只要不被别人知道就行
    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) {
        // Get a session. We're ignoring the error resulted from decoding an
        // existing session: Get() always returns a session, even if empty.
    
        // 获取一个session对象,session-name是session的名字
        session, err := store.Get(r, "session-name")
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }
    
        // 在session中存储值
        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的值

    // 删除
    // 将session的最大存储时间设置为小于零的数即为删除
    session.Options.MaxAge = -1
    session.Save(r, w)
    
  • 相关阅读:
    redis安装及简单命令
    struts2 第二天
    初学struts2-入门案列
    hibernate第二天
    hibernate入门
    同义词,索引,表分区
    表空间,序列
    orcale函数
    orcale错题分析
    orcale开篇
  • 原文地址:https://www.cnblogs.com/liuqingzheng/p/16154434.html
Copyright © 2020-2023  润新知