Go Cookie

作者: JunChow520 | 来源:发表于2021-01-23 03:45 被阅读0次
    • HTTP无状态协议

    HTTP本身是一种无状态的连接协议,因此每个请求或响应都是独立的。服务端每次处理完一个客户端请求之后就会断开连接,所以每次请求或响应与之前和之后的请求或响应是没有任何关系的。换句话说,HTTP自身不具备保存之前发送过的请求或响应的状态。

    由于HTTP无状态的特性,在Web应用中跟踪用户状态的方法可分为四种:

    • 建立包含有跟踪数据的隐藏字段
    • 重写包含额外参数的URL
    • 使用持续的Cookie
    • 使用服务端的Session

    Cookie和Session是Web应用比较常见的概念,它们的目的都是为了克服HTTP协议的无状态问题。

    Cookie

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

    Cookie机制

    Cookie是由服务端生成后发送给User-Agent(比如浏览器),User-Agent会将Cookie的key/value保存到本地磁盘上指定目录下的文本文件内。当下次请求相同网站时会发送该Cookie给i服务器,不过前提是浏览器必须提前设置了启用Cookie。

    Cookie的key/value键和值可以由服务端自行定义,这样服务端可知道对应用户是否合法以及是否需要重新登录等。服务器可设置或读取Cookie中包含的信息,借此来维护用户更服务端会话的状态。

    Cookie是HTTP协议头的一部分,用户浏览器和服务器之间传递数据。当客户端第一次向服务器发起请求时,服务端会创建一个Cookie,并通过HTTP响应头中的Set-Cookie属性将Cookie信息返回给客户端,并通知客户端保存。

    Cookie

    Cookie的传递流程

    1. 客户端首次发送请求,此时请求报文中没有Cookie信息。
    GET /index HTTP/1.1
    Host: www.baidu.com
    
    1. 服务端收到请求后生成Cookie信息,同时发送响应报文。
    HTTP/1.1 200 OK
    Server: Apache
    <Set-Cookie: sid=57111807181018; path=/;expires=Web,10-OCT-12 07:12:20 GMT>
    Content-Type: text/plain; charset=UTF-8
    
    1. 客户端再次向服务端发起请求报文,此时会自动发送保存的Cookie信息。
    GET /image/ HTTP1.1
    HOST: www.baidu.com
    Cookie: sid=57111807181018
    

    Cookie中主要包含NAME(名称)、path(路径)、domain(域名)、expires(有效期)、max-age(过期时间)等属性。

    Cookie是针对单个域名domain的,因此不同域名之间的Cookie是相互独立的。

    通过设置Cookie的maxAge属性可以设置Cookie的过期时间,若不设置maxAge则被成为会话Cookie,会话Cookie的生命周期从浏览器打开到关闭为止,主要关闭浏览器窗口,会话Cookie就会消失。会话Cookie一般保存在内存而非磁盘。

    通过设置过期时间(setMaxAge(606024)),浏览器会将Cookie保存在本地磁盘中,对于关闭后重新打开的浏览器,这些Cookie依旧有效。

    Cookie过期时间的设置方式

    cookie.setMaxAge(0); //不记录Cookie
    cookie.setMaxAge(-1);//会话级Cookie,关闭浏览器后立即失效。
    cookie.setMaxAge(60 * 60);//过期时间设置为1小时
    

    Go Cookie

    Go语言标准库net/http中定义了Cookie的数据结构,用于表示一个出现在HTTP响应头Set-Cookie的值或HTTP请求头中Cookie的值。

    Cookie的数据结构

    type Cookie struct{
        Name string
        Value string
    
        Path string
        Domain string
        Expires time.Time
        RawExpires string
    
        MaxAge int
        Secure bool
        HttpOnly bool
        Raw string
        Unparsed []string
    }
    
    字段 描述
    Expires Cookie过期时间,使用绝对时间,比如2020/12/21 00:00:00。
    MaxAge Cookie的最大生存秒数时长,使用相对时间,比如300秒。
    Secure Cookie是否需要安全传输,当为真时表示只有HTTPS才会传输该Cookie。
    HttpOnly Cookie是否能够被JavaScripit读取其值
    Unparsed 表示未解析的键值对的原始文本

    没有设置Expires字段的Cookie称为会话Cookie或临时Cookie,这种Cookie在浏览器窗口关闭时会自动删除。设置了Expires字段的Cookie称为持久Cookie,这种Cookie会一直存在,直到指定时间到期或手动删除。

    Expires和MaxAge都可以用于设置Cookie的过期时间,Expires字段设置的Cookie在指定时间点过期,MaxAge字段设置的是Cookie自创建之后能够存活多少秒。虽然HTTP 1.1中废弃了Expires并推荐使用MaxAge代替,但几乎所有浏览器仍然支持Expires。微软的IE6/IE7/IE8并不支持MaxAge。为了更好地移植性,优先推荐使用Expires。

    最大存活期MaxAge取值范围

    MaxAge 描述
    0 表示尚未设置Max-Age属性
    <0 表示立即删除Cookie,等价于Max-Age:0
    >0 表示存在Max-Age属性,且单位为秒。

    获取Cookie

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

    • 解析并返回请求的Cookie头设置的所有Cookie
    func (r *Request) Cookies() []*Cookie
    
    • 返回请求中名为name的Cookie,若未找到则会返回nilErrNoCookie
    func (r *Request) Cookie(name string) (*Cookie, error)
    

    例如:

    cookie := http.Cookie{Name:"username", Value:"junchow", Expires:expiration}
    
    • 添加Cookie可通过AddCookie方法向请求中添加一个Cookie
    func (r *Request) AddCookie(c *Cookie)
    

    设置Cookie

    Go语言中设置Cookie是通过net/http标准包中的SetCookie函数实现的,它会在responseWriter的头域中添加Set-Cookie头,其值为cookie

    http.SetCookie(responseWriter, &cookie)
    

    例如:在HTTP响应中通过设置Set-Cookie头新增Cookie并将其发送给客户端浏览器

    package main
    
    import (
        "fmt"
        "net/http"
        "time"
    )
    
    func indexHandler(responseWriter http.ResponseWriter, request *http.Request) {
        //获取Cookie
        cookie,err := request.Cookie("sessionid")
        if cookie == nil && err != nil {
            expires := time.Now().Add(time.Hour)
            //设置Cookie
            cookie := &http.Cookie{
                Name:"sessionid",
                Value:"1jl3dndo0ex82kal",
                MaxAge:60*60,
                Expires: expires,
                Domain:"127.0.0.1:9090",
                Path:"/",
                HttpOnly:true,
            }
            http.SetCookie(responseWriter, cookie)
        }else{
            //cookie:(*http.Cookie)(nil), err:http: named cookie not present
            fmt.Printf("cookie:%#v, err:%v\n", cookie, err)
        }
    
        responseWriter.Write([]byte("hello"))
    }
    
    func main() {
        http.HandleFunc("/", indexHandler)
        http.ListenAndServe("0.0.0.0:9090", nil)
    }
    

    查看请求

    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
    Accept-Encoding: gzip, deflate, br
    Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7
    Cache-Control: max-age=0
    Connection: keep-alive
    Cookie: sessionid=1jl3dndo0ex82kal
    Host: 127.0.0.1:9090
    sec-ch-ua: "Chromium";v="88", "Google Chrome";v="88", ";Not A Brand";v="99"
    sec-ch-ua-mobile: ?0
    Sec-Fetch-Dest: document
    Sec-Fetch-Mode: navigate
    Sec-Fetch-Site: none
    Sec-Fetch-User: ?1
    Upgrade-Insecure-Requests: 1
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36
    

    例如:直接通过HTTP响应头Set-Cookie来设置Cookie

    package main
    
    import (
        "fmt"
        "net/http"
        "net/url"
    )
    
    func indexHandler(responseWriter http.ResponseWriter, request *http.Request) {
        cookie := http.Cookie{
            Name:"account",
            Value:url.QueryEscape("junchow"),
            HttpOnly:true,
        }
        responseWriter.Header().Add("Set-Cookie", cookie.String())
        fmt.Fprintln(responseWriter, "hello world")
    }
    
    func main() {
        http.HandleFunc("/", indexHandler)
        http.ListenAndServe("0.0.0.0:9090", nil)
    }
    

    查看HTTP响应头

    Content-Length: 12
    Content-Type: text/plain; charset=utf-8
    Date: Fri, 22 Jan 2021 19:44:31 GMT
    Set-Cookie: account=junchow; HttpOnly
    

    相关文章

      网友评论

          本文标题:Go Cookie

          本文链接:https://www.haomeiwen.com/subject/lktvoktx.html