網站首頁 編程語言 正文
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 Secure
- Cookie HttpOnly
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
相關推薦
- 2022-08-23 Python解析器Cpython的GIL解釋器鎖工作機制_python
- 2022-06-24 Go單體服務開發最佳實踐總結_Golang
- 2023-10-11 hutool工具類 | huTool的基本使用
- 2022-03-17 .NET?6開發TodoList應用引入數據存儲_實用技巧
- 2022-04-19 C語言內存管理及初始化細節示例詳解_C 語言
- 2023-01-17 SqlServer事務語法及使用方法詳解_MsSql
- 2022-11-15 C語言自研定時器計劃任務語法詳解_C 語言
- 2023-04-07 關于C#中的Invoke示例詳解_C#教程
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支