✨✨ 欢迎大家来到景天科技苑✨✨
🎈🎈 养成好习惯,先赞后看哦~🎈🎈
🏆 作者简介:景天科技苑
🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。
🏆《博客》:Python全栈,Golang开发,PyQt5和Tkinter桌面开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi,flask等框架,云原生K8S,linux,shell脚本等实操经验,网站搭建,数据库等分享。所属的专栏:Go语言开发零基础到高阶实战
景天的主页:景天科技苑
文章目录
Gin框架中的Cookie和Session
在深入探讨Cookie和Session之前,我们需要了解HTTP协议的无状态特性。简单来说,HTTP是一种无状态协议,即每次请求与响应之间都是独立的,服务器不会记住之前的状态信息。这意味着,当用户从一个页面跳转到另一个页面时,服务器无法自动识别这是同一个用户的请求。为了实现跨请求的数据共享,我们可以使用Cookie和Session。本文将结合实际案例,详细介绍在Go语言的Gin框架中如何使用Cookie和Session。
一、Cookie的详细用法
1. Cookie的基本概念
Cookie是一种存储在客户端浏览器中的键值对数据,用于在客户端和服务器之间传递信息。每次向服务器发送请求时,浏览器都会自动携带这些Cookie信息。
2. 设置Cookie
在Gin框架中,可以通过c.SetCookie方法设置Cookie。以下是该方法的主要参数:
name:Cookie的名称。
value:Cookie的值。
maxAge:Cookie的过期时间(秒)。如果只想设置Cookie的保存路径而不想设置存活时间,可以在此参数中传递nil。
path:Cookie的路径。
domain:Cookie的域名作用域。本地调试时配置为localhost,正式上线时配置为域名。
secure:当此值为true时,Cookie在HTTP中是无效的,仅在HTTPS中有效。
httpOnly:如果设置了此属性,则通过程序(如JS脚本)将无法读取到Cookie信息,防止XSS攻击。
示例代码:
package main
import("github.com/gin-gonic/gin")funcTestHandler(c *gin.Context){// 获取客户端是否携带Cookie 获取名为"username"的Cookie// 如果不存在将myCookie设为lucas
mycookie, err := c.Cookie("username")if err !=nil{
mycookie ="lucas"}// 给客户端设置Cookie// func (c *Context) SetCookie(name, value string, maxAge int, path, domain string, secure, httpOnly bool)
c.SetCookie("username", mycookie,60*60,"/","localhost",false,true)//响应客户端字符串
c.String(200,"测试Cookie")}funcmain(){
r := gin.Default()// 创建路由,默认使用Logger()和Recovery()中间件// func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes
r.GET("/cookie", TestHandler)
r.Run(":8888")}
可以看到服务端给浏览器客户端设置的cookie
3. 获取cookie
要获取客户端请求中的Cookie,可以使用c.Cookie()方法。以下是一个示例:
package main
import("github.com/gin-gonic/gin""net/http")funcgetCookie(c *gin.Context){// 获取名为"username"的Cookie
cookie, err := c.Cookie("username")if err !=nil{
c.String(http.StatusOK,"未找到Cookie")return}
c.String(http.StatusOK,"Cookie值:"+cookie)}funcmain(){
r := gin.Default()
r.GET("/getCookie", getCookie)
r.Run(":8080")}
由于我们设置了一条cookie,username为lucas,所以能获取到
4. 删除Cookie
删除Cookie实际上是通过设置其过期时间为负数来实现的。
package main
import("github.com/gin-gonic/gin""net/http")funcdeleteCookie(c *gin.Context){// 删除名为"username"的Cookie//实际上就是设置maxAge为负数
c.SetCookie("username","",-1,"/","localhost",false,true)
c.String(http.StatusOK,"删除Cookie成功")}funcmain(){
r := gin.Default()//在请求处,将handlers函数传进来
r.GET("/deleteCookie", deleteCookie)
r.Run(":8080")}
在上面的代码中,c.SetCookie(“username”, “”, -1, “/”, “localhost”, false, true)方法会将名为"username"的Cookie过期时间设置为过去的时间戳,从而删除该Cookie。
二、Session的详细用法
1. Session的基本概念
Session是一种记录客户状态的机制,与Cookie不同的是,Session数据保存在服务器上。当客户端浏览器第一次访问服务器并发送请求时,服务器端会创建一个Session对象,生成一个类似于key-value的键值对,然后将value保存到服务器,将key(通常是一个Cookie)返回到浏览器(客户端)。浏览器下次访问时会携带这个key,服务器通过这个key找到对应的Session数据。
2. Session的工作原理
- 1: 我们的请求在默认情况下是无状态的,所谓的无状态就是指,gin定义一个路由地址,在浏览器访问以后,也就是 发起一个request,到response的过程,整个过程结束后,并不会在服务器端存储数据。这样就会造成一个问题, 无法解决各路由请求之间数据的共享问题。
- 2:如何解决这个问题呢?其实也就是session
- 3:session是一种服务器端的存储技术,其实在底层就是一个全局的map[string][any]对象。它可以把一些需要各个 路由间共享的数据进行存储在内存中,直到服务器关闭或者超时才会清除。
- 4:有了session,为什么还有有sessionId呢?因为要区分是那个业务的数据,因为底层是map,所以大部分情况下都会 用sessionId作为key.
- 5:有了session,为啥还要cookie技术呢,cookie是一种客户端的存储技术,在创建session的时候,每次都会把这个 sessionId写入到客户端浏览器的cookie中,后续给未来的每个路由请求都携带这个sessionId, 到服务端的map种去匹配 对应自己的数据信息。
- 6:从而达到数据的共享。
3. Sesison的应用场景
第一次登录,服务器给客户端颁发一个唯一的sessionId, 并通过http的响应头返回。客户端(浏览器)发现返回的数据中有cookie数据就把这个cookie数据存放到内存。下次再发送http请求时,把内存中的cookie数据再塞到http请求头中,一并发给服务器,服务器在解析请求时,发现请求头中有cookie,就开始识别cookie中的sessionId,拿到sessionId,我们就知道这个请求时由哪个客户端发送来的了。
4. 在Gin框架中使用Session
Gin框架本身并不内置对Session的支持,但可以使用第三方的Session中间件来实现。其中比较常用的是github.com/gin-contrib/sessions。
1. 安装依赖
首先,需要安装Session中间件:
go get github.com/gin-contrib/sessions
2. 创建基于内存的Session
Session存储引擎有多种实现方式,如基于内存、Redis、MongoDB等。以下是一个基于内存的示例:
package main
import("github.com/gin-contrib/sessions""github.com/gin-contrib/sessions/memstore""github.com/gin-gonic/gin")funcmain(){
r := gin.Default()// 创建基于内存的存储引擎// func NewStore(keyPairs ...[]byte) Store
store := memstore.NewStore([]byte("secret11111"))// 设置Session中间件// func Sessions(name string, store Store) gin.HandlerFunc
r.Use(sessions.Sessions("mysession", store))
r.GET("/",func(c *gin.Context){// 初始化Session对象
session := sessions.Default(c)// 设置Session数据
session.Set("username","zhangsan")// 保存Session数据
session.Save()
c.JSON(200, gin.H{"message":"Session设置成功"})})
r.GET("/get",func(c *gin.Context){// 初始化Session对象
session := sessions.Default(c)// 获取Session数据
username := session.Get("username")
c.JSON(200, gin.H{"username": username})})
r.Run(":8080")}
在上面的代码中,memstore.NewStore([]byte(“secret11111”))创建了一个基于内存的Session存储引擎,sessions.Sessions(“mysession”, store)设置了Session中间件,其中"mysession"是Session的名称,也是Cookie的名称。
当我们访问首页,设置session成功
当我们访问/get,可以获取session
在控制器中使用Session
在Gin框架的控制器中,可以使用sessions.Default©方法获取当前的Session对象,然后调用Set、Get和Save等方法来设置、获取和保存Session数据。
3. 创建基于Redis存储Session
如果希望将Session数据保存在Redis中,可以使用github.com/gin-contrib/sessions/redis包。以下是一个示例:
首先,安装Redis存储引擎的包:
go get -u github.com/gin-contrib/sessions/redis
然后,配置Redis存储引擎:
package main
import("github.com/gin-contrib/sessions""github.com/gin-contrib/sessions/redis""github.com/gin-gonic/gin")funcmain(){
r := gin.Default()// 创建基于Redis的存储引擎// func NewStore(size int, network, address, password string, keyPairs ...[]byte) (Store, error)// func NewStoreWithDB(size int, network, address, password, DB string, keyPairs ...[]byte) (Store, error) 指定DB
store,_:= redis.NewStoreWithDB(10,"tcp","10.10.0.100:6379","123456","0",[]byte("secret"))// 设置Session中间件
r.Use(sessions.Sessions("mysession", store))
r.GET("/",func(c *gin.Context){// 初始化Session对象
session := sessions.Default(c)// 设置Session数据
session.Set("username","jingtian")// 保存Session数据
session.Save()
c.JSON(200, gin.H{"message":"Session设置成功"})})
r.GET("/get",func(c *gin.Context){// 初始化Session对象
session := sessions.Default(c)// 获取Session数据
username := session.Get("username")
c.JSON(200, gin.H{"username": username})})
r.Run(":8080")}
浏览器访问首页,session保存成功
登录redis查看,可以看到session
5. Session的基本操作
在获取到Session对象后,我们可以对其进行设置、获取、删除和清除等操作。需要注意的是,每次对Session进行修改后,都需要调用session.Save()方法来保存更改。
设置Session:
session.Set("username","zhangsan")
session.Save()
获取Session:
username := session.Get("username")
删除Session中的某个键值对:
session.Delete("username")
session.Save()
清除整个Session:
session.Clear()
session.Save()
三、注意事项
- Cookie的Secure属性:当设置为
true
时,Cookie仅在HTTPS中有效。在生产环境中,为了安全起见,建议启用HTTPS并设置Secure属性。 - Cookie的HttpOnly属性:设置为
true
时,可以防止通过JS脚本读取Cookie,增加安全性。 - Session的过期时间:可以通过设置Session存储引擎的Options来配置过期时间等参数。
- 跨域问题:在涉及跨域请求时,需要确保服务器正确配置了CORS(跨域资源共享)中间件,并允许携带Credentials。
- Gob编解码器:Gin框架的Session中间件使用Gob作为编解码器。当存储复杂类型(如struct、map等)时,需要先注册这些类型,否则会报错“gob: type not registered for…”。
四、总结
本文详细介绍了在Go语言的Gin框架中如何使用Cookie和Session来实现跨请求的数据共享。通过合理配置和使用这些机制,我们可以有效地管理客户端状态,提高应用程序的可用性和安全性。希望本文能对你有所帮助!
版权归原作者 景天科技苑 所有, 如有侵权,请联系我们删除。