Go Web:Cookie

Cookie用来解决http协议无状态的问题。

首先,在服务端生成Cookie,然后在http响应header中设置Set-Cookie字段,客户端会读取到Set-Cookie字段后,会将cookie信息存储起来,下次继续访问服务端时,会在http请求中设置Cookie字段并发送给服务端,服务端可以解析这个Cookie字段,从而知道这个客户端之前已经和自己有过会话(上下文),然后再执行相应的逻辑代码。

Cookie分为两种类型:session cookie和persistent cookie。

  • Session Cookie也称为临时Cookie,客户端只会将cookie数据存储在http client进程的内容中,不会保存到磁盘文件中(或其它存储设备),浏览器关闭(或者说http client进程退出)的时候,cookie就删除了
  • persistent cookie是持久化cookie,浏览器退出也不删除,而是根据服务端发送cookie时设置的过期时长判断cookie是否过期,只要cookie还有效,客户端就会携带cookie访问服务端

Cookie struct

$ go doc http.cookie

type Cookie struct {
        Name  string
        Value string

        Path       string    // optional
        Domain     string    // optional
        Expires    time.Time // optional
        RawExpires string    // for reading cookies only

        // MaxAge=0 means no 'Max-Age' attribute specified.
        // MaxAge<0 means delete cookie now, equivalently 'Max-Age: 0'
        // MaxAge>0 means Max-Age attribute present and given in seconds
        MaxAge   int
        Secure   bool
        HttpOnly bool
        Raw      string
        Unparsed []string // Raw text of unparsed attribute-value pairs
}

func (c *Cookie) String() string

一个Cookie代表一个http cookie。服务端可以设置多个Set-Cookie字段发送给客户端。

Name和Value分别设置这个cookie的key/value。一定要有至少一个能唯一区分客户端的ID类的value。

Expires指定cookie到什么时候过期,是一个时间值。当指定为过去的时间值时,表示这个cookie已经过期。

MaxAge也用来设置cookie什么时候过期,MaxAge为负数或等于0表示立即过期,MaxAge大于0表示过多少秒之后过期。

MaxAge和Expires都可以设置cookie持久化时的过期时长,Expires是老式的过期方法,如果可以,应该使用MaxAge设置过期时间,但有些老版本的浏览器不支持MaxAge。如果要支持所有浏览器,要么使用Expires,要么同时使用MaxAge和Expires。

Path和Domain设置访问哪些路径或域名范围的主机时应该携带这个cookie。如果不设置,则访问所有路径、该Domain下的主机都携带cookie。

cookie.Path("/WEB16");
    代表访问WEB16应用中的任何资源都携带cookie
cookie.Path("/WEB16/cookietest");
    代表访问WEB16中的cookietest时才携带cookie信息
cookie.Domain(".foo.com");
    这对foo.com域下的所有主机都生效(如www.foo.com),但不包括子域www.abc.foo.com

Secure和HttpOnly字段为cookie提供一些保护机制。这两个cookie属性的介绍,参见:

Cookie有一个String()方法,用来将Cookie实例转换成字符串。转化成字符串之后就可以直接设置在Header中。

例如,下面是登录youtube的时候,对方发送给我的cookie:

设置Cookie并发送给客户端

package main

import (
    "fmt"
    "net/http"
)

func setCookie(w http.ResponseWriter, r *http.Request) {
    // 定义两个cookie
    c1 := http.Cookie{
        Name:  "first_cookie",
        Value: "Go Programming",
    }
    c2 := http.Cookie{
        Name:     "second_cookie",
        Value:    "Go Web Programming",
        HttpOnly: true,
    }
    // 设置Set-Cookie字段
    w.Header().Set("Set-Cookie", c1.String())
    w.Header().Add("Set-Cookie", c2.String())
    fmt.Fprintf(w, "%s\n%s\n", c1.String(), c2.String())
}

func main() {
    server := http.Server{
        Addr: "127.0.0.1:8080",
    }
    http.HandleFunc("/set_cookie", setCookie)
    server.ListenAndServe()
}

访问http://127.0.0.1:8080/set_cookie时,查看Header将显式Set-Cookie字段。

$ curl -i http://127.0.0.1:8080/set_cookie
HTTP/1.1 200 OK
Set-Cookie: first_cookie="Go Programming"
Set-Cookie: second_cookie="Go Web Programming"; HttpOnly
Date: Tue, 27 Nov 2018 10:12:44 GMT
Content-Length: 75
Content-Type: text/plain; charset=utf-8

first_cookie="Go Programming"
second_cookie="Go Web Programming"; HttpOnly

http包提供了一个SetCookie()函数,可以直接用来设置Set-Cookie字段。

func SetCookie(w ResponseWriter, cookie *Cookie)

注意,第二个字段是指针类型的Cookie

修改前面的示例,使用SetCookie()函数发送Set-Cookie字段:

func setCookie(w http.ResponseWriter, r *http.Request) {
    c1 := http.Cookie{
        Name:  "first_cookie",
        Value: "Go Programming",
    }
    c2 := http.Cookie{
        Name:     "second_cookie",
        Value:    "Go Web Programming",
        HttpOnly: true,
    }
    http.SetCookie(w, &c1)
    http.SetCookie(w, &c2)
}

取得客户端携带的cookie

由于客户端发起请求时,如果携带cookie,是直接放在Request的Cookie Header中的。所以,可以通过Request取得客户端携带的cookie信息。当然,也可以通过Request的方法Cookie()或Cookies()取得cookie信息。

func (r *Request) Cookie(name string) (*Cookie, error)
func (r *Request) Cookies() []*Cookie
  • Cookie(Name)只取某个cookie
  • Cookies()取所有的cookie

下面是通过Request Header的方式取Cookie的示例:

package main

import (
    "fmt"
    "net/http"
)

func setCookie(w http.ResponseWriter, r *http.Request) {
    c1 := http.Cookie{
        Name:  "first_cookie",
        Value: "Go Programming",
    }
    c2 := http.Cookie{
        Name:     "second_cookie",
        Value:    "Go Web Programming",
        HttpOnly: true,
    }
    http.SetCookie(w, &c1)
    http.SetCookie(w, &c2)
}

func getCookie(w http.ResponseWriter, r *http.Request) {
    cookie := r.Header.Get("Cookie")
    fmt.Fprintf(w, "%s\n", cookie)
}

func main() {
    server := http.Server{
        Addr: "127.0.0.1:8080",
    }
    http.HandleFunc("/set_cookie", setCookie)
    http.HandleFunc("/get_cookie", getCookie)
    server.ListenAndServe()
}

在访问http://127.0.0.1:8080/set_cookie之后不要关闭浏览器,再次访问http://127.0.0.1:8080/get_cookie,将输出:

first_cookie="Go Programming"; second_cookie="Go Web Programming"

或者,使用curl记录cookie,并下次访问时读取cookie:

$ curl -c a.cookie http://127.0.0.1:8080/set_cookie
$ curl -b a.cookie http://127.0.0.1:8080/get_cookie
first_cookie="Go Programming"; second_cookie="Go Web Programming"

下面是改用Request的Cookie()和Cookies()方法取cookie:

func getCookie(w http.ResponseWriter, r *http.Request) {
    cookie, err := r.Cookie("first_cookie")
    if err != nil {
        fmt.Fprintf(w, "Cat't get Cookie")
    }
    cookies := r.Cookies()
    fmt.Fprintf(w, "%s\n%s\n", cookie, cookies)
}

访问结果:

$ curl -c a.cookie http://127.0.0.1:8080/set_cookie
$ curl -b a.cookie http://127.0.0.1:8080/get_cookie
first_cookie="Go Programming"
[first_cookie="Go Programming" second_cookie="Go Web Programming"]

设置cookie过期示例:发送临时消息

有时候可能想要让客户端的某些操作只显示一次相关消息,例如post一篇帖子失败后,应该显示失败信息,但下次再访问不应该再显示这些失败信息。

通过设置cookie过期的技巧,可以实现一些一次性操作。设置cookie过期的方式是设置MaxAge为负数或0,为了兼容所有浏览器,可以设置Expires为过去的一段时间。

下面的示例中,将一段数据使用URL格式编码后作为flash cookie的值。当客户端访问set_message的时候,就会在http Client进程中保存这段cookie。再访问show_message的时候,handler解析客户端携带的cookie,并设置一个Set-Cookie字段,这个字段的作用是使之前保存的cookie过期。然后输出解码后客户端携带的cookie的值。再次刷新show_message,将得到不同的输出结果。

package main

import (
    "encoding/base64"
    "fmt"
    "net/http"
    "time"
)

func set_message(w http.ResponseWriter, r *http.Request) {
    msg := []byte("Hello World")
    cookie := http.Cookie{
        Name:  "flash",
        Value: base64.URLEncoding.EncodeToString(msg),
    }
    http.SetCookie(w, &cookie)
}

func show_message(w http.ResponseWriter, r *http.Request) {
    cookie, err := r.Cookie("flash")
    if err != nil {
        if err == http.ErrNoCookie {
            fmt.Fprintln(w, "no messages to show")
        }
    } else {
        expire_cookie := http.Cookie{
            Name:    "flash",
            MaxAge:  -1,
            Expires: time.Unix(1, 0),
        }
        http.SetCookie(w, &expire_cookie)
        value, _ := base64.URLEncoding.DecodeString(cookie.Value)
        fmt.Fprintln(w, string(value))
    }
}
func main() {
    server := http.Server{
        Addr: "127.0.0.1:8080",
    }
    http.HandleFunc("/set_message", set_message)
    http.HandleFunc("/show_message", show_message)
    server.ListenAndServe()
}

使用curl测试。注意,首先访问set_message的时候,保存cookie到b.cookie文件。再访问show_message的时候,也要带上-c b.cookie将已保存的cookie设置为过期,之后再访问show_message就会出现预期的结果:

$ curl -c b.cookie http://127.0.0.1:8080/set_message
$ curl -b b.cookie -c b.cookie http://127.0.0.1:8080/show_message
Hello World

$ curl -b b.cookie -c b.cookie http://127.0.0.1:8080/show_message
no messages to show

原文地址:https://www.cnblogs.com/f-ck-need-u/p/10035803.html

时间: 2024-10-05 11:14:24

Go Web:Cookie的相关文章

客户端技术:Cookie 服务端技术:HttpSession

客户端技术:Cookie 服务端技术:HttpSession 07. 五 / android基础 / 没有评论 一.会话技术1.什么是会话:客户打开浏览器访问一个网站,访问完毕之后,关闭浏览器.这个过程称之为一个会话.就如同打电话.2.会话在编程中主要解决的问题是:保存各个用户的数据信息.3.保存用户各自数据的主要技术:客户端技术:Cookie服务端技术:HttpSession 二.Cookie1.获取Cookie采用request.getCookies()2.设置Cookie采用respons

关于session的实现:cookie与url重写

本文讨论的语境是java EE servlet. 我们都知道session的实现主要两种方式:cookie与url重写,而cookie是首选(默认)的方式,因为各种现代浏览器都默认开通cookie功能,但是每种浏览器也都有允许cookie失效的设置. 由于浏览器默认启动cookie功能,而且普通客户一般都不会取消cookie功能.久而久之,我们写代码的时候,也就不会在意session的具体实现,其实这里面还是有很多值得注意的地方,尤其在用户取消cookie功能的情况下. 一 servlet se

JavaWeb学习之转发和重定向、会话技术:cookie、session、验证码实例、URLConnection使用(下载网页)(4)

1.转发和重定向 HttpServletResponse response 转发: RequestDispatcher dispatcher = request.getRequestDispatcher("/secondServlet"); request.setAttribute("pwd","123");//这里设置的值在secondServlet中可以获取到 dispatcher.forward(request, response);//调

【黑马程序员】第9课:Cookie与HttpSession详解

<pre> day09 昨天内容回顾 (1)response *response里面对应http协议里面的对应的方法 *在response里面做了四个案例(不包含验证码)代码至少写三遍 *验证码的案例,看懂就可以了. *重点掌握看不清换一张实现 *Response向页面输出中文乱码解决(****) (2)request *获取客户机信息和头信息的方法 *获取表单提交的数据 *获取表单提交中文数据乱码问题解决(****) *request域 *重定向和转发的区别 思维导图 1.JSP入门(代码位

【Head First Servlets and JSP】笔记11:cookie

容器如何知道客户是谁?(这并不是HTTP能实现的!IP地址不能唯一的标识用户,另外,非必要不采用HTTPS 继续mark孤傲苍狼的博客,百科全书 cookie——Header——字典——键值对—— 延长cookie的保质期 容器会做cookie的所有工作! 1.先搭建一个简单的测试程序——使用cookie记录用户上一次访问的时间(tomcat+web.xml+servlet <?xml version="1.0" encoding="ISO-8859-1" ?

会话管理:Cookie与Session技术

会话管理是web开发技术中用来跟踪用户并保持用户信息的技术.举一个例子,当用户在请求一个页面后,又接着请求了另外一个页面,这个时候,http是没有办法判断这两个请求是不是来自同一个用户,因为http协议是一个无状态协议,http协议没有办法维护两个事物之间的联系.这个时候就轮到会话管理华丽登场了. 会话管理有两种方式:一个是cookie,另一个是session.这两种会话方式又有什么不同呢?不着急,我们接下来就会分析二者的特点. cookie是服务器存放在用户计算机里面的数据,这些数据包括了我们

javaWeb学习总结(7)-关于session的实现:cookie与url重写

本文讨论的语境是java EE servlet.我们都知道session的实现主要两种方式:cookie与url重写,而cookie是首选(默认)的方式,因为各种现代浏览器都默认开通cookie功能,但是每种浏览器也都有允许cookie失效的设置.由于浏览器默认启动cookie功能,而且普通客户一般都不会取消cookie功能.久而久之,我们写代码的时候,也就不会在意session的具体实现,其实这里面还是有很多值得注意的地方,尤其在用户取消cookie功能的情况下.一 servlet sessi

浏览器存储:cookie

Cookie是什么:cookie是指存储在用户本地终端上的数据,同时它是与具体的web页面或者站点相关的.Cookie数据会自动在web浏览器和web服务器之间传输,也就是说HTTP请求发送时,会把保存在该请求域名下的所有cookie值发送给web服务器,因此服务器端脚本是可以读.写存储在客户端的cookie的操作. cookie的有效期:cookie默认情况下的有效期是很短暂的,一旦用户关闭浏览器,cookie保存的数据就会丢失.如果想要延长cookie的有效期,可以通过设置HTTP头信息中的

常见的浏览器端的存储技术:cookie

工作原理: cookie是存在用户硬盘中,用户每次访问站点时,Web应用程序都可以读取Cookie包含的信息.当用户再次访问这个站点时,浏览器就会在本地硬盘上查找与该 URL 相关联的 Cookie.如果该Cookie存在,浏览器就将它加到requestheader的Cookie字段中,与http请求一起发送到该站点.(cookie是存于用户硬盘的一个文件,这个文件通常对应于一个域名,也就是说,cookie可以跨越一个域名下的多个网页,但不能跨越多个域名使用.) 1.优点:兼容性好 分担了服务器