Cookie和Session
Cookie和Session
Cookie 和 Session 是 Web 开发绕不开的一个环节,本文介绍 Cookie 和 Session 的原理以及在Go 语言中如何操作
- 浏览器发送请求的时候,自动把携带该站点之前存储的Cookie信息。
2.服务端可以设置Cookie数据。
3. Cookie是针对单个域名的,不同域名之间的Cookie是独立的。
4. Cookie数据可以配置过期时间,过期的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 // 未解析的“属性-值”对的原始文本 }
2 设置 Cookie
func SetCookie(w ResponseWriter, 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)
删除 Cookie
cookie := http.Cookie{Name: "testcookiename", Path: "/", MaxAge: -1} http.SetCookie(w, &cookie)
设置 Cookie
cookie := http.Cookie{Name: "testcookiename", Value: "testcookievalue", Path: "/", MaxAge: 86400} http.SetCookie(w, &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() }
"net/http" 操作 cookie
package main import ( "net/http") func SayHello(w http.ResponseWriter, req *http.Request) { w.Write([]byte("Hello")) } func ReadCookieServer(w http.ResponseWriter, req *http.Request) { // read cookie cookie, err := req.Cookie("testcookiename") if err == nil { cookievalue := cookie.Value w.Write([]byte("<b>cookie的值是:" + cookievalue + "</b>n")) } else { w.Write([]byte("<b>读取出现错误:" + err.Error() + "</b>n")) } } func WriteCookieServer(w http.ResponseWriter, req *http.Request) { cookie := http.Cookie{Name: "testcookiename", Value: "testcookievalue", Path: "/", MaxAge: 86400} http.SetCookie(w, &cookie) w.Write([]byte("<b>设置cookie成功。</b>n")) } func DeleteCookieServer(w http.ResponseWriter, req *http.Request) { cookie := http.Cookie{Name: "testcookiename", Path: "/", MaxAge: -1} http.SetCookie(w, &cookie) w.Write([]byte("<b>删除cookie成功。</b>n")) } func main() { http.HandleFunc("/", SayHello) http.HandleFunc("/readcookie", ReadCookieServer) http.HandleFunc("/writecookie", WriteCookieServer) http.HandleFunc("/deletecookie", DeleteCookieServer) http.ListenAndServe(":80", nil) }
gin 框架中操作cookie
// gin 框架操作 Cookie // todo 一次性获取所有的Cookie func main() { router := gin.Default() // 添加 Cookie router.POST("/addCookie", func(context *gin.Context) { var cookie string var err error // 获取 Cookie 没有 cookie err 会出现错误 if cookie, err = context.Cookie("ljs"); err != nil { // 没有 cookie 设置 cookie context.SetCookie("ljs", "love hsm", 3600 * 24 , "/", "localhost", false, true) context.JSON(http.StatusOK, gin.H{ "msg" : fmt.Sprintf("添加 cookie 成功"), }) return } context.JSON(http.StatusOK, gin.H{ "msg" : fmt.Sprintf("添加 cookie 失败, 原来的 cookie 是 %s", cookie), }) return }) // 删除 Cookie router.DELETE("/deleteCookie", func(context *gin.Context) { var cookie string var err error // 获取 Cookie 没有 cookie err 会出现错误 if cookie, err = context.Cookie("ljs"); err != nil { // 没有 cookie, 不用删除 context.JSON(http.StatusOK, gin.H{ "msg" : fmt.Sprintf("没有您需要删除的 cookie "), }) return } context.SetCookie("ljs", "love hsm", -1 , "/", "localhost", false, true) context.JSON(http.StatusOK, gin.H{ "msg" : fmt.Sprintf("删除 cookie 成功, cookie_name = %s, cookie_value = %s", "ljs", cookie), }) return }) // 修改 Cookie router.PUT("/updateCookie", func(context *gin.Context) { // 获取 Cookie var err error if _, err = context.Cookie("ljs"); err != nil { // 没有 cookie context.JSON(http.StatusOK, gin.H{ "msg" : fmt.Sprintf("找不到您需要修改的 cookie_name = %s", "ljs"), }) return } context.SetCookie("ljs", "love 个屁", 3600 * 12, "/", "localhost", false, true) context.JSON(http.StatusOK, gin.H{ "msg" : fmt.Sprintf("cookie 修改成功 cookie_name= %s, cookie_value = %s", "ljs", "love 个屁"), }) return }) // 获取 Cookie router.GET("/getCookie", func(context *gin.Context) { var cookie string var err error if cookie, err = context.Cookie("ljs"); err != nil { // 没有获取到 cookie context.JSON(http.StatusOK, gin.H{ "msg" : fmt.Sprintf("没有您获取的cookie_name = %s", "ljs"), }) return } context.JSON(http.StatusOK, gin.H{ "msg" : fmt.Sprintf("获取的 cookie 是 %s", cookie), }) return }) 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其实是共通性的东西,不限于语言和框架。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!