Cookie和Session

Cookie和Session

HTTP 无状态协议

HTTP 本身是一个无状态的连接协议,无状态的意思是:每条请求/响应都是独立进行的,服务端每处理完一个客户端的请求之后就会断开连接,并且每条请求/响应与其之前(或之后)的请求/响应是没有任何关系的。即HTTP自身不具备保存之前发送过的请求或者响应的功能。

比如当我们打开微博的登录页,输入用户名和密码之后,浏览器将这些数据发送给服务器端,服务端验证成功之后,跳转到了我们的微博首页,但是接着如果我们希望查看自己聊天消息,由于 HTTP 的这种无状态性,服务端将无法知道我们在上一HTTP请求中已经通过了验证,从而无法正确的处理这次请求。

为了解决这个问题。我们首先想到的办法是可以在所有的请求中都带上用户名和密码,这种方法虽然可行,但也大大加重了服务器的负担(每个请求都需到数据库验证)。更好的办法其实是使用 Cookie 与 Session 机制。
在 Web 应用中跟踪用户状态的办法有以下四种:

  • 建立包含有跟踪数据的隐藏字段(比如使用)
  • 重写包含额外参数的URL(文末会介绍)
  • 使用持续的Cookie
  • 使用 Session

Session 和 Cookie 是 Web 程序中较为常见的两个概念。它们的目的相同,都是为了解决 http 协议无状态的问题。

Cookie

Cookie 实际上是一小段由客户端(如浏览器)保存在本地的文本文件,它记录了你的用户ID、密码、浏览过的网页、浏览时间等信息。当客户端再次访问同一个网站时,客户端就会把请求连同 Cookie 一起发送给服务端,服务端通过检查该 Cookie,就可以辨认用户状态了。

Cookie 的传递流程

Cookie 是 HTTP 协议头的一部分,用于浏览器和服务器之间传递信息。
当客户端第一次向服务端发起请求时,服务端会创建一个 Cookie,并通过 HTTP 响应头中的 Set-Cookie 属性,来将 Cookie 信息返回给客户端,并通知客户端保存起来。
当客户端再次向服务端发起请求时,客户端就会把之前保存在本地的 Cookie 放入请求头中一并发送给服务端,服务端获得 Cookie 之后,就可以得到客户端的状态信息了。
在这里插入图片描述

Cookie 中主要包含了*NAME(名称)、path(路径)、domain(域名)、expires(有效期)、max-age(过期时间)*几种不同的属性,它们各自起到不同的作用。例如通过设置 Cookie 的 maxAge 属性可以设置 Cookie 的过期时间,不设置 maxAge 被称为会话 Cookie,会话 Cookie 生命周期为从创建浏览器到关闭浏览器为止,只要关闭浏览器窗口,会话 Cookie 就会消失,它一般保存在内存中,而不是硬盘中。

如果设置了过期时间(setMaxAge(606024)),浏览器就会把 Cookie 保存在硬盘上,对于关闭后重新打开的浏览器,这些 Cookie 依旧有效。

cookie过期时间设置方式:

  1. cookie.setMaxAge(0);//不记录cookie
  2. cookie.setMaxAge(-1);//会话级cookie,关闭浏览器失效
  3. cookie.setMaxAge(60*60);//过期时间为1小时

实例演示

  1. set方法
r.GET("/setCookie", func(c *gin.Context) {
   // 设置cookie
   c.SetCookie("cookie_name", "cookie_value", 3600, "/", "localhost", false, true)
   /*
      name cookie的名称
      value cookie的值
      maxAge int, 单位为秒
      path cookie所在目录
      domain string,域名
      secure 是否智能通过https访问
      httpOnly bool  是否允许通过js获取自己的cookie
   */
   c.JSON(http.StatusOK, gin.H{
      "message": "set cookie success.",
   })
})

在这里插入图片描述在这里插入图片描述

  1. get方法
r.GET("/getCookie", func(c *gin.Context) {
   // 读取cookie,根据cookie名读取
   cookie, err := c.Cookie("cookie_name")
   if err != nil {
      // 直接返回cookie值
      c.JSON(http.StatusOK, gin.H{"message": "get cookie fail"})
      return
   }
   c.JSON(http.StatusOK, gin.H{"cookie_name": cookie})
})

在这里插入图片描述
3.delete方法

r.GET("/delCookie", func(c *gin.Context) {
   // 删除cookie, 设置cookie MaxAge设置为-1,表示删除cookie
   c.SetCookie("cookie_name", "cookie_value", -1, "/", "localhost", false, true)
   c.JSON(http.StatusOK, gin.H{
      "message": "delete cookie success.",
   })
})

在这里插入图片描述在这里插入图片描述

session

除了使用 Cookie 之外,Web 应用程序还经常使用 Session 来跟踪用户状态,与 Cookie 保存在客户端浏览器不同的是,Session 是将状态信息保存在了服务端上。服务端使用一种类似散列表的结构(也可能就是使用散列表)来保存信息。

session的工作原理

  1. 客户端第一次向服务器端发送请求时,服务端程序会为此客户端创建一个session,并生成一个与此session相关联的sessionId。(sessionId的值应该是一个不会重复并且难以伪造的字符串)
  2. 服务端向客户端返回响应时,同时会将 sessionId 一起返回给客户端,客户端会将 sessionId 字符串保存下来。
  3. 当客户端再次访问服务端时,将 sessionId 一并发送给服务端。
  4. 服务端获取从客户端发送过来的 sessionId,就可以根据这个id 获取保存在服务器中相应的数据了
  5. 当其他客户端也访问服务端时,就又会产生一个新的sessionId,类似以上的步骤进行处理。

整个客户端和服务端的交互过程可以概括为以下三个步骤:

  • 客户端第一次发送请求时,服务端创建 Session,并生成唯一标识符 SessionId
  • 服务端将 SessionId 发送给客户端(一般来说有两种常用的方式:Cookie 和 URL 重写)
  • 客户端再次向服务端发送请求时一并将 SessionId 发送给服务端。

gin配置session

gin框架在处理session时有专门的中间件,我们可以直接使用。
中间件:github.com/gin-contrib/sessions ,我们直接安装依赖:github.com/gin-contrib/sessions ,即可引入使用

session官方案例


```go
package main
import (
    // 导入session包
    "github.com/gin-contrib/sessions"
    // 导入session存储引擎
    "github.com/gin-contrib/sessions/cookie"
    // 导入gin框架包
    "github.com/gin-gonic/gin"
)
func main() {
    r := gin.Default()   
             
    // 创建基于cookie的存储引擎,shuiche 参数是用于加密的密钥,可以随便填写
 	store := cookie.NewStore([]byte("shuiche"))
    
    // 设置session中间件,参数mysession,指的是session的名字,也是cookie的名字
    // store是前面创建的存储引擎
    r.Use(sessions.Sessions("mysession", store))
    
    r.GET("/test", func(c *gin.Context) {
        // 初始化session对象
        session := sessions.Default(c)                
        // 通过session.Get读取session值
        // session是键值对格式数据,因此需要通过key查询数据
        if session.Get("hello") != "world" {
            // 设置session数据,()
            session.Set("hello", "world")
            // 删除session数据
            session.Delete("tizi365")
            // 保存session数据
            session.Save()
            // 删除整个session
            session.Clear()
        }
                
        c.JSON(200, gin.H{"hello": session.Get("hello")})
    })
    r.Run(":8000")
}

实例演示

  1. set方法

```go
r.GET("/test", func(c *gin.Context) {
   // 初始化session对象
   session := sessions.Default(c)

   session.Set("hello", "world")
   session.Set("hello01", "world01")
   session.Set("hello02", "world02")
   session.Save()

   c.JSON(200, gin.H{
      "hello":   session.Get("hello"),
      "hello01": session.Get("hello01"),
      "hello02": session.Get("hello02"),
   })
})

在这里插入图片描述

  1. delete方法
r.GET("/test", func(c *gin.Context) {
   // 初始化session对象
   session := sessions.Default(c)

   session.Delete("hello")
   session.Delete("hello02")
   session.Save()

   c.JSON(200, gin.H{
      "hello":   session.Get("hello"),
      "hello01": session.Get("hello01"),
      "hello02": session.Get("hello02"),
   })
})

在这里插入图片描述

3.clear方法

r.GET("/test", func(c *gin.Context) {    // 初始化session对象    session := sessions.Default(c)

   session.Clear()    //session.Save()

   c.JSON(200, gin.H{
      "hello":   session.Get("hello"),
      "hello01": session.Get("hello01"),
      "hello02": session.Get("hello02"),   
   }) 
})

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值