Cookie和Session

Cookie和Session

Cookie和Session是Web开发绕不开的一个环节,本文介绍了Cookie和Session的原理及在Go语言中如何操做Cookie。git

Cookie的由来

HTTP协议是无状态的,这就存在一个问题。github

无状态的意思是每次请求都是独立的,它的执行状况和结果与前面的请求和以后的请求都无直接关系,它不会受前面的请求响应状况直接影响,也不会直接影响后面的请求响应状况。数据库

一句有意思的话来描述就是人生只如初见,对服务器来讲,每次的请求都是全新的。浏览器

状态能够理解为客户端和服务器在某次会话中产生的数据,那无状态的就觉得这些数据不会被保留。会话中产生的数据又是咱们须要保存的,也就是说要“保持状态”。所以Cookie就是在这样一个场景下诞生。安全

Cookie是什么

在 Internet 中,Cookie 其实是指小量信息,是由 Web 服务器建立的,将信息存储在用户计算机上(客户端)的数据文件。通常网络用户习惯用其复数形式 Cookies,指某些网站为了辨别用户身份、进行 Session 跟踪而存储在用户本地终端上的数据,而这些数据一般会通过加密处理。服务器

Cookie的机制

Cookie是由服务器端生成,发送给User-Agent(通常是浏览器),浏览器会将Cookie的key/value保存到某个目录下的文本文件内,下次请求同一网站时就发送该Cookie给服务器(前提是浏览器设置为启用cookie)。Cookie名称和值能够由服务器端开发本身定义,这样服务器能够知道该用户是不是合法用户以及是否须要从新登陆等,服务器能够设置或读取Cookies中包含信息,借此维护用户跟服务器会话中的状态。cookie

总结一下Cookie的特色:网络

  1. 浏览器发送请求的时候,自动把携带该站点以前存储的Cookie信息。
  2. 服务端能够设置Cookie数据。
  3. Cookie是针对单个域名的,不一样域名之间的Cookie是独立的。
  4. Cookie数据能够配置过时时间,过时的Cookie数据会被系统清除。

查看Cookie

咱们使用Chrome浏览器打开一个网站,打开开发者工具查看该网站保存在咱们电脑上的Cookie数据。session

Go操做Cookie

标准库net/http中定义了Cookie,它表明一个出如今HTTP响应头中Set-Cookie的值里或者HTTP请求头中Cookie的值的HTTP cookie数据结构

type Cookie struct {
    Name       string
    Value      string
    Path       string
    Domain     string
    Expires    time.Time
    RawExpires string
    // MaxAge=0表示未设置Max-Age属性
    // MaxAge<0表示马上删除该cookie,等价于"Max-Age: 0"
    // MaxAge>0表示存在Max-Age属性,单位是秒
    MaxAge   int
    Secure   bool
    HttpOnly bool
    Raw      string
    Unparsed []string // 未解析的“属性-值”对的原始文本
}

设置Cookie

net/http中提供了以下SetCookie函数,它在w的头域中添加Set-Cookie头,该HTTP头的值为cookie。

func SetCookie(w ResponseWriter, cookie *Cookie)

获取Cookie

Request对象拥有两个获取Cookie的方法和一个添加Cookie的方法:

获取Cookie的两种方法:

// 解析并返回该请求的Cookie头设置的全部cookie
func (r *Request) Cookies() []*Cookie

// 返回请求中名为name的cookie,若是未找到该cookie会返回nil, ErrNoCookie。
func (r *Request) Cookie(name string) (*Cookie, error)

添加Cookie的方法:

// AddCookie向请求中添加一个cookie。
func (r *Request) AddCookie(c *Cookie)

gin框架操做Cookie

import (
    "fmt"

    "github.com/gin-gonic/gin"
)

func main() {
    router := gin.Default()
    router.GET("/cookie", func(c *gin.Context) {
        cookie, err := c.Cookie("gin_cookie") // 获取Cookie
        if err != nil {
            cookie = "NotSet"
            // 设置Cookie
            c.SetCookie("gin_cookie", "test", 3600, "/", "localhost", false, true)
        }
        fmt.Printf("Cookie value: %s \n", cookie)
    })

    router.Run()
}

Session

Session的由来

Cookie虽然在必定程度上解决了“保持状态”的需求,可是因为Cookie自己最大支持4096字节,以及Cookie自己保存在客户端,可能被拦截或窃取,所以就须要有一种新的东西,它能支持更多的字节,而且他保存在服务器,有较高的安全性。这就是Session

问题来了,基于HTTP协议的无状态特征,服务器根本就不知道访问者是“谁”。那么上述的Cookie就起到桥接的做用。

用户登录成功以后,咱们在服务端为每一个用户建立一个特定的session和一个惟一的标识,它们一一对应。其中:

  • Session是在服务端保存的一个数据结构,用来跟踪用户的状态,这个数据能够保存在集群、数据库、文件中;
  • 惟一标识一般称为Session ID会写入用户的Cookie中。

这样该用户后续再次访问时,请求会自动携带Cookie数据(其中包含了Session ID),服务器经过该Session ID就能找到与之对应的Session数据,也就知道来的人是“谁”。

总结而言:Cookie弥补了HTTP无状态的不足,让服务器知道来的人是“谁”;可是Cookie以文本的形式保存在本地,自身安全性较差;因此咱们就经过Cookie识别不一样的用户,对应的在服务端为每一个用户保存一个Session数据,该Session数据中可以保存具体的用户数据信息。

另外,上述所说的Cookie和Session实际上是共通性的东西,不限于语言和框架。

相关文章
相关标签/搜索