Gin 中单一Cookie的应用
1 )路由处理
package routers
import (
"gin-demo/controllers/web"
"github.com/gin-gonic/gin"
)
func WebRoutersInit(r *gin.Engine) {
webRouters := r.Group("/")
{
webRouters.GET("/", web.WebCtrl{}.Index)
webRouters.GET("/setcookie", web.WebCtrl{}.SetCookie)
webRouters.GET("/getcookie", web.WebCtrl{}.GetCookie)
webRouters.GET("/delcookie", web.WebCtrl{}.DelCookie)
}
}
2 ) 控制器处理
package web
import (
"net/http"
"github.com/gin-gonic/gin"
)
type WebCtrl struct{}
// 设置 cookie
func (con WebCtrl) SetCookie(c *gin.Context) {
// 设置 cookie
// 第一个
c.SetCookie("username", "张三", 3600, "/", "localhost", false, true)
// 第二个
c.SetCookie("hobby", "吃饭 睡觉", 5, "/", "localhost", false, true)
// 响应
c.String(http.StatusOK, "set cookie")
}
// 获取 cookie
func (con WebCtrl) GetCookie(c *gin.Context) {
// 获取 cookie
username, _ := c.Cookie("username")
hobby, _ := c.Cookie("hobby")
// 响应
c.String(http.StatusOK, "username=%v----hobby=%v", username, hobby)
}
// 删除 cookie
func (con WebCtrl) DelCookie(c *gin.Context) {
// 删除 cookie
c.SetCookie("username", "张三", -1, "/", "localhost", false, true) // 删除一个
// 响应
c.String(http.StatusOK, "delete cookie")
}
-
设置cookie时,设置了两个不同过期时间的cookie
-
5s 后第一个cookie 自动丢失
-
访问 /delcookie 路由,第二个路由被主动删除
-
HTTP 是无状态协议,当你浏览了一个页面
-
然后转到同一个网站的另一个页面,服务器无法认识到这是同一个浏览器在访问同一个网站
-
每一次的访问,都是没有任何关系的
-
如果我们要实现多个页面之间共享数据的话
-
我们就可以使用 Cookie 或者 Session 实现
-
cookie 是存储于访问者计算机的浏览器中
-
可以让我们用同一个浏览器访问同一个域名的时候共享数据
-
所以,cookie的功能
- 保持用户登录状态
- 保存用户浏览的历史记录
- 猜你喜欢,智能推荐
- 电商网站的加入购物车
-
cookie的文档
- https://gin-gonic.com/zh-cn/docs/examples/cookie/
-
设置cookie时的API
c.SetCookie(name, value string, maxAge int, path, domain string, secure, httpOnly bool)
- 第一个参数 key
- 第二个参数 value
- 第三个参数 过期时间
- 如果只想设置 Cookie 的保存路径而不想设置存活时间
- 可以在第三个参数中传递 nil
- 第四个参数 cookie 的路径
- 第五个参数 cookie 的路径 Domain 作用域
- 本地调试配置成 localhost , 正式上线配置成域名
- 第六个参数是 secure
- 当 secure 值为 true 时,cookie 在 HTTP 中是无效,在 HTTPS 中才有效
- 第七个参数 httpOnly
- 是微软对 COOKIE 做的扩展, 如果在 COOKIE 中设置了“httpOnly”属性
- 则通过程序(JS 脚本、applet 等)将无法读取到 COOKIE 信息,防止 XSS 攻击产生
多级域名共享 cookie
- 不管二级或多级域名,可以设置根域名来共享数据
- 分别把 a.xyz.com 和 b.xyz.com, 以及 c.b.xyz.com 解析到我们的服务器
- 我们想的是用户在 a.xyz.com 中设置 Cookie 信息后
- 在 b.xyz.com 以及 c.b.xyz.com 中获取刚才设置的cookie
- 也就是实现多个二级域名共享 cookie,这时候就可以这样设置 cookie
c.SetCookie("usrename", "张三", 3600, "/", ".xyz.com", false, true)
单体架构 基于 cookie 存储 session
概述
1 ) 单单使用 cookie 的限制
- 单单基于 cookie 的设定,只能读取单个客户端中的数据,不能做到数据在服务端共享
- 服务端Cookie技术是将数据存储在用户的浏览器上,每次浏览器发送请求时
- 都会携带这些Cookie数据发送到服务器。Cookie的大小通常受到限制
- 大多数浏览器对单个Cookie的大小有4096字节的限制
- 尽管现在一些新的浏览器和客户端设备支持更大的Cookie
- 此外,用户可以选择禁用Cookie功能,这会影响Cookie的正常使用
2 )基于 cookie 的 session 技术
- 与Cookie不同,Session技术将数据存储在服务器上
- 这意味着Session没有存储大小的限制,只受限于服务器的内存大小
- Session在用户访问期间一直存在在服务器上,直到会话结束或服务器决定删除它
- 由于Session存储在服务器上,因此相比Cookie,它更安全,不容易被篡改
- 但是,如果服务器上有大量的Session,会占用较多的服务器资源
- 可能会影响服务器的性能
示例
1 )主程序配置 在 main.go 中
package main
import (
"github.com/gin-contrib/sessions"
"github.com/gin-contrib/sessions/cookie"
"github.com/gin-gonic/gin"
)
func main() {
// 创建一个默认的路由引擎
r := gin.Default()
// ... 跳过其他
// 在路由配置之上,配置session中间件
cookieSessionSecret := "sdfdssdsfs_s?d2sdfsf@^s_" // 是用于加密的密钥
// 创建基于 cookie 的存储引擎
store := cookie.NewStore([]byte(cookieSessionSecret))
// 配置session的中间件 store是前面创建的存储引擎,我们可以替换成其他存储引擎
r.Use(sessions.Sessions("xxproject_session", store))
// ... 跳过其他
}
2 ) 路由配置
package routers
import (
"gin-demo/controllers/web"
"github.com/gin-gonic/gin"
)
func WebRoutersInit(r *gin.Engine) {
webRouters := r.Group("/")
{
webRouters.GET("/", web.WebCtrl{}.Index)
webRouters.GET("/setsession", web.WebCtrl{}.SetSession)
webRouters.GET("/getsession", web.WebCtrl{}.GetSession)
webRouters.GET("/delsession", web.WebCtrl{}.DelSession)
}
}
3 ) controller 控制器
package web
import (
"net/http"
"github.com/gin-contrib/sessions" // 则个是用于 直接获取 cookie 内容的
"github.com/gin-gonic/gin"
)
type WebCtrl struct{}
// 设置 session服务器托管网
func (con WebCtrl) SetSession(c *gin.Context) {
session := sessions.Default(c)
// 配置session的过期时间
session.Options(sessions.Options{
// MaxAge: 3600 * 6, // 6hrs MaxAge单位是秒
MaxAge: 5, // 5 s 过期
})
session.Set("username", "张三 111")
session.Save() // 设置session的时候必须调用
// 响应
c.String(http.StatusOK, "set session: %v", session.Get("username"))
}
// 获取 session
func (con WebCtrl) GetSession(c *gin.Context) {
session := sessions.Default(c)
username := session.Get("username")
// 响应
c.String(http.StatusOK, "get session username=%v", username)
}
// 删除 session
func (con WebCtrl) DelSession(c *gin.Context) {
session := sessions.Default(c)
session.Delete("username")
session.Save() // 这将从 Cookie中 中删除 session 数据
username := session.Get("username") // 获取 session username
// 响应
c.String(http.StatusOK, "delete session %v", username)
}
- 基于cookie的 session 技术如上是基本使用程序
- 需要注意的是,关于 session 删除同步到 cookie 删除是自动设置的
- 调用 session 的 Delete 和 Save 方法来更新 Cookie
- 由于 session 数据已经被删除,这个操作会创建一个新的、空的 Cookie
- 这实际上会导致浏览器端的旧 Cookie 过期并被删除,所以无需我们控制cookie
分布式架构下 基于 redis 存储 session
概述
- 如果项目部署在多台机器上,单体架构下的session无法共享,需要借助第三方来同步数据
- 这时候就会用到 redis 或其他服务器存储技术,在负载均衡下的多台机器共享数据的场景
- 就是分布式架构下的 session 应用场景
示例
1 )主程序 main.go
package main
import (
"github.com/gin-contrib/sessions"
"github.com/gin-contrib/sessions/redis"
"github.com/gin-gonic/gin"
)
func main() {
// 创建一个默认的路由引擎
r := gin.Default()
// ... 跳过其他
// 在路由配置之上,配置session中间件
redisSessionSecret := "sdfdssdsfs_s?d2sdfsf@^s_" // 是用于加密的密钥
// 配置session中间件
store, _ := redis.NewStore(10, "tcp", "localhost:6379", "", []byte(redisSessionSecret))
r.Use(sessions.Sessions("mysession", store))
// ... 跳过其他
}
2 ) 路由和控制器同上面的 cookie based session 示例,这里不再赘述
3 )注意
- 初始化基于 redis 的session存储引擎, 参数说明:
- 第 1 个参数 – re服务器托管网dis 最大的空闲连接数
- 第 2 个参数 – 数通信协议 tcp 或者 udp
- 第 3 个参数 – redis 地址, 格式,host:port
- 第 4 个参数 – redis 密码
- 第 5 个参数 – session 加密密钥
- 同步删除 session 的时候,redis 的数据也会被同步删除,同时浏览器的Cookie数据也会同步消失
- 有时候需要手动删除,比如客户端调用退出登录接口的时候,手动调用 session的删除和保存方法
其他
- 关于多 session 和 其他存储引擎的 session 都在文档中
- 参考:https://github.com/gin-contrib/sessions
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
武汉源创会回归,4月20聊聊大模型” 原文作者:NGINX 原文链接:什么是 gRPC? 转载来源:NGINX 开源社区 NGINX 唯一中文官方社区 ,尽在nginx.org.cn gRPC(Google Remote Procedure Call,Goog…