引言
在深入探讨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" ) func testhandler(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") } func main() { 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" ) func getcookie(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) } func main() { 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" ) func deletecookie(c *gin.context) { // 删除名为"username"的cookie //实际上就是设置maxage为负数 c.setcookie("username", "", -1, "/", "localhost", false, true) c.string(http.statusok, "删除cookie成功") } func main() { 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" ) func main() { 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" ) func main() { 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来实现跨请求的数据共享。通过合理配置和使用这些机制,我们可以有效地管理客户端状态,提高应用程序的可用性和安全性。
以上就是关于gin框架中的cookie和session的使用方法的详细内容,更多关于gin框架cookie和session的使用的资料请关注代码网其它相关文章!
发表评论