<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
Cookie用來解決http協定無狀態的問題。
首先,在伺服器端生成Cookie,然後在http響應header中設定Set-Cookie欄位,使用者端會讀取到Set-Cookie欄位後,會將cookie資訊儲存起來,下次繼續存取伺服器端時,會在http請求中設定Cookie欄位並行送給伺服器端,伺服器端可以解析這個Cookie欄位,從而知道這個使用者端之前已經和自己有過對談(上下文),然後再執行相應的邏輯程式碼。
Cookie分為兩種型別:session cookie和persistent cookie。
$ 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:
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, "%sn%sn", 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,是直接放在Request的Cookie Header中的。所以,可以通過Request取得使用者端攜帶的cookie資訊。當然,也可以通過Request的方法Cookie()或Cookies()取得cookie資訊。
func (r *Request) Cookie(name string) (*Cookie, error) func (r *Request) 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, "%sn", 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, "%sn%sn", 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"]
有時候可能想要讓使用者端的某些操作只顯示一次相關訊息,例如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
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45