Gin 应用多实例部署session问题、session参数与刷新

news2025/1/19 14:38:19

文章目录

    • 一、Gin Session 存储的实现方案
    • 二、`memstore`:基于内存的实现
      • 2.1 基本使用
      • 2.2 关键参数
    • 三、使用`redis`:多实例部署
      • 3.1 使用redis优势
      • 3.2 基本使用
    • 四、信息安全的三个核心概念
    • 五、Gin Session 参数
      • 5.1 参数介绍
    • 六、Session 自动刷新

一、Gin Session 存储的实现方案

  • cookie:基于cookie的实现,不安全,一般不会使用。
  • gorm:基于 GORM 的实现
  • memcached:基于 Memcached 的实现
  • memstore:基于内存的实现,一般单实例部署用的比较多,或者本地测试。
  • mongo:基于 MongoDB 的实现
  • postgres:基于 PostgreSQL 的实现
  • redis:基于 Redis 的实现,多实例部署,应该无脑选 redis 实现。
  • tester:用于测试的实现

其实Gin 中的session 是通过github.com/gorilla/sessions实现的,只不过做了二次封装。

二、memstore:基于内存的实现

2.1 基本使用

memstoregithub.com/gin-contrib/sessions库提供的一个基于内存的Session存储后端。它将Session数据存储在应用程序的内存中,适用于小型应用或用于开发和测试目的。以下是一个使用memstore的简单示例:

  1. 安装gin-contrib/sessions库:

    go get -u github.com/gin-contrib/sessions
    
  2. 使用memstore存储Session:

    package main
    
    import (
    	"github.com/gin-contrib/sessions"
    	"github.com/gin-contrib/sessions/memstore"
    	"github.com/gin-gonic/gin"
    )
    
    func main() {
    	// 初始化Gin引擎
    	router := gin.Default()
        // 用内存存储 session
    	// 这是基于内存的实现,第一个参数是 authentication key,最好是 32 或者64 位
    	//第二个参数是 encryption key
    	store := memstore.NewStore([]byte("moyn8y9abnd7q4zkq2m73yw8tu9j5ixm"),[]byte("o6idlo2cb9f9pb6h46fimllw481ldebi"))
    	router.Use(sessions.Sessions("mysession", store))
    
    	// 路由示例
    	router.GET("/set", func(c *gin.Context) {
    		// 设置Session
    		session := sessions.Default(c)
    		session.Set("key", "value")
    		session.Save()
    
    		c.JSON(200, gin.H{"message": "Session set"})
    	})
    
    	router.GET("/get", func(c *gin.Context) {
    		// 获取Session
    		session := sessions.Default(c)
    		value := session.Get("key")
    
    		c.JSON(200, gin.H{"key": value})
    	})
    
    	// 启动服务
    	router.Run(":8080")
    }
    
    

    在上述示例中,我们使用了memstore.NewStore创建一个基于内存的Session存储后端。记得在实际应用中,根据实际需求选择适当的Session存储后端,例如,在生产环境中可能更常见的是使用像Redis这样的持久化存储。

    请注意,memstore是基于内存的,如果应用程序重新启动,所有存储在内存中的Session数据将被清除。因此,它最适用于短期的Session需求,而不适用于长期的数据存储。在实际生产环境中,需要根据应用程序的需求选择合适的Session存储后端。

2.2 关键参数

我们通过NewStore入口进入,可以看到,官方要求传入鉴权和加密的Key对于Key的长度越长越复杂越安全。

在正常情况下,要传入两个关键参数。第一个参数是 认证密钥(authentication key),最好是 32 或者 64 位。第二个参数是 加密密钥(encryption key)。

// 用内存存储 session
// 这是基于内存的实现,第一个参数是 authentication key,最好是 32 或者64 位
//第二个参数是 encryption key
store := memstore.NewStore([]byte("moyn8y9abnd7q4zkq2m73yw8tu9j5ixm"),[]byte("o6idlo2cb9f9pb6h46fimllw481ldebi"))
// cookie 的名字叫做sessions
ser.Use(sessions.Sessions("sessions", store))// 登录校验
ser.Use(middleware.NewLoginMiddlewareBuilder().Build())

三、使用redis:多实例部署

3.1 使用redis优势

在分布式环境下(包括单例应用多实例部署),都需要确保 Session 在每一个实例上都可以访问到,而单节点只能访问当前环境的Session。

3.2 基本使用

在使用Redis作为Session存储时,你需要使用Gin框架的github.com/gin-contrib/sessions中间件,并选择一个支持Redis的Session存储后端,比如github.com/gin-contrib/sessions/redis

以下是一个基本的使用示例:

  1. 安装依赖:

    go get -u github.com/gin-contrib/sessions
    go get -u github.com/gin-contrib/sessions/redis
    
  2. 使用Redis存储Session:

    package main
    
    import (
    	"github.com/gin-contrib/sessions"
    	"github.com/gin-contrib/sessions/redis"
    	"github.com/gin-gonic/gin"
    )
    
    func main() {
    	// 初始化Gin引擎
    	router := gin.Default()
    
    	// 使用Redis存储Session
    	store, err := redis.NewStore(
    		16,               // 最大空闲链接数量,过大会浪费,过小将来会触发性能瓶颈
    		"tcp",            // 指定与Redis服务器通信的网络类型,通常为"tcp"
    		"localhost:6379", // Redis服务器的地址,格式为"host:port"
    		"",               // Redis服务器的密码,如果没有密码可以为空字符串
    		[]byte("95osj3fUD7fo0mlYdDbncXz4VD2igvf0"), // authentication key
    		[]byte("0Pf2r0wZBpXVXlQNdpwCXN4ncnlnZSc3"), // encryption key
    	)
    
    	if err != nil {
    		panic(err)
    	}
    
    	// 设置Session中间件
    	router.Use(sessions.Sessions("mysession", store))
    
    	// 路由示例
    	router.GET("/set", func(c *gin.Context) {
    		// 设置Session
    		session := sessions.Default(c)
    		session.Set("key", "value")
    		session.Save()
    
    		c.JSON(200, gin.H{"message": "Session set"})
    	})
    
    	router.GET("/get", func(c *gin.Context) {
    		// 获取Session
    		session := sessions.Default(c)
    		value := session.Get("key")
    
    		c.JSON(200, gin.H{"key": value})
    	})
    
    	// 启动服务
    	router.Run(":8080")
    }
    
    

    在上述示例中,我们使用了redis.NewStore创建一个基于Redis的Session存储后端。你需要提供Redis服务器的地址、密码和密钥等信息。

四、信息安全的三个核心概念

  1. 身份认证(Authentication): 身份认证是确认用户或系统的身份是否合法的过程。在身份认证中,用户提供的身份信息(例如用户名和密码、生物特征等)被验证以确定其是否有权访问系统或资源。常见的身份认证方式包括用户名密码认证、多因素认证(例如使用手机验证码或硬件令牌)、生物特征认证等。
  2. 数据加密(Encryption): 数据加密是通过使用算法将信息转化为密文,以确保只有具备正确密钥的人或系统能够解密和访问原始信息。数据加密对于保护敏感信息、防止数据泄露和维护隐私非常重要。常见的加密算法包括对称加密(同一个密钥用于加密和解密)和非对称加密(使用一对密钥,一个用于加密,另一个用于解密)。
  3. 权限控制(Authorization): 权限控制是确保用户或系统在身份认证成功后只能访问其被授权的资源和执行其被授权的操作的过程。这包括定义用户或系统的角色、分配权限、限制访问范围等。权限控制有助于防止未经授权的访问和确保系统的安全性。

五、Gin Session 参数

5.1 参数介绍

在Gin框架中,Session的参数可以通过Options方法来传入OptionOptions方法用于配置Session的一些参数,以满足应用程序的需求。

参数详细解释:

字段含义示例值
PathCookie的路径“/”
DomainCookie的域“your-domain.com”
MaxAge最大生存时间(秒)3600
Secure是否仅通过HTTPS传输true
HttpOnly是否禁止通过JavaScript访问Cookietrue
SameSiteSameSite属性http.SameSiteLaxMode

举个例子:

package main

import (
	"github.com/gin-contrib/sessions"
	"github.com/gin-gonic/gin"
	"net/http"
)

func main() {
	// 初始化Gin引擎
	router := gin.Default()

	// 配置Session
	store := sessions.NewCookieStore([]byte("your-secret-key"))
	store.Options(sessions.Options{
		Path:     "/",
		Domain:   "your-domain.com",
		MaxAge:   3600, // 设置为3600秒,即1小时
		Secure:   true, // 仅通过HTTPS传输Cookie
		HttpOnly: true, // 禁止通过JavaScript访问Cookie
		SameSite: http.SameSiteLaxMode, // SameSite属性,限制在顶级导航时发送
	})
	router.Use(sessions.Sessions("mysession", store))

	// 路由示例
	router.GET("/set", func(c *gin.Context) {
		// 设置Session
		session := sessions.Default(c)
		session.Set("key", "value")
		session.Save()

		c.JSON(200, gin.H{"message": "Session set"})
	})

	router.GET("/get", func(c *gin.Context) {
		// 获取Session
		session := sessions.Default(c)
		value := session.Get("key")

		c.JSON(200, gin.H{"key": value})
	})

	// 启动服务
	router.Run(":8080")
}

六、Session 自动刷新

实现方式,在中间件中设置一个更新时间:

// LoginMiddlewareBuilder 结构体的 Build 方法,用于构建 Gin 中间件
func (l *LoginMiddlewareBuilder) Build() gin.HandlerFunc {
	// 使用 gob 注册 time.Now(),以便在 Session 中存储 time.Time 类型
	gob.Register(time.Now())

	// 返回一个 Gin 中间件函数
	return func(ctx *gin.Context) {
		// 检查当前请求路径是否为不需要登录校验的路径
		if ctx.Request.URL.Path == "/users/login" ||
			ctx.Request.URL.Path == "/users/signup" {
			// 如果是不需要登录校验的路径,直接返回,不进行后续的登录检查
			return
		}

		// 获取默认的 Session
		sess := sessions.Default(ctx)

		// 获取 Session 中存储的 userId
		id := sess.Get("userId")

		// 如果 userId 不存在,说明用户未登录,返回未授权状态码
		if id == nil {
			ctx.AbortWithStatus(http.StatusUnauthorized)
			return
		}

		// 获取 Session 中的 updateTime
		updateTime := sess.Get("update_time")

		// 设置 Session 的 userId,并配置 Session 的过期时间为 60 秒
		sess.Set("userId", id)
		sess.Options(sessions.Options{
			MaxAge: 60,
		})

		now := time.Now()

		// 如果 updateTime 为空,说明是第一次登录,设置 update_time 并保存 Session
		if updateTime == nil {
			sess.Set("update_time", now)
			if err := sess.Save(); err != nil {
				panic(err)
			}
		}

		// 如果 updateTime 不为空,说明已经登录过,检查是否超过 10 秒,超过则刷新 update_time 并保存 Session
		updateTimeVal, _ := updateTime.(time.Time)
		if now.Sub(updateTimeVal) > time.Second*10 {
			sess.Set("update_time", now)
			if err := sess.Save(); err != nil {
				panic(err)
			}
		}
	}
}

缺点:由于这种方式每次都要从Redis中读写数据,在高并发中并不适合。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1416291.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

idea中yml文件没有提示解决办法

两步解决yml文件不显示提示,yaml文件显示提示问题 1、在插件中心,先下载下图两个插件 2、在Editor》File Types新增文件类型,文件名匹配规则需要将yaml和yml的都加上,加好之后,重启idea,即刻生效。

《汇编语言:基于linux环境》eatsyscall汇编程序

当阅读此书,作者编写了一个这样的程序,我也想试一下。照着书中的代码写了下,可以使用nasm正常编译,ld也可以正常链接,但是无法正常执行。总是报错。 ; nasm -f elf64 -g -F stabs eatsyscall.asm ; ld -o eatsysca…

CTF CRYPTO 密码学-6

题目名称:敲击 题目描述: 方方格格,不断敲击 “wdvtdz qsxdr werdzxc esxcfr uygbn” 解题过程: step1:根据题目描述敲击,wdvtdz对应的字符为x step2:依此类推r,z,o&…

张维迎《博弈与社会》笔记(4)导论:社会最优与帕累托标准

本节我们将从社会的角度来评判人类行为:一个社会应该采取什么样的标准来判断个人行为?具体地讲,我们需要知道,从社会的角度来评判,什么样的行为是正当的,什么样的行为是不正当的;什么样的行为应…

安装 java 的 JDK

前几天重装系统以后想起来要重装 java 的JDK 安装地址 Windows 下的 JDK 数据包有三种可选的下载:Windows x64 Compressed Archive、Windows x64 Installer 和 Windows x64 MSI Installer。其中,前者为 JDK 的免安装版本,后两者均为 JDK 的离…

05-Nacos-配置中心接入

1、pom依赖 <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency> 2、配置文件 spring:application:name: nacos-config## 当前环境&#xff0c;这个和…

【JS基础】事件对象event、环境对象this、事件的高级操作

文章目录 一、事件对象1.1 事件对象是什么&#xff1f;1.2 使用方法 二、环境对象this以及回调函数2.1 它是什么&#xff1f;2.2 演示示例 三、事件的高级操作3.1 事件流3.2 事件捕获3.3 事件冒泡以及阻止冒泡3.4 事件解绑3.5 mouseover和mouseenter事件的区别3.6 事件委托它是…

架构篇21:高性能负载均衡-算法

文章目录 轮询加权轮询负载最低优先性能最优类Hash 类源地址 HashID Hash小结负载均衡算法数量较多,而且可以根据一些业务特性进行定制开发,抛开细节上的差异,根据算法期望达到的目的,大体上可以分为下面几类。 任务平分类:负载均衡系统将收到的任务平均分配给服务器进行处…

MongoDB:从容器使用到 Mongosh、Python/Node.js 数据操作

文章目录 1. 容器与应用之间的关系介绍2. 使用 Docker 容器安装 MongoDB3. Mongosh 操作3.1 Mongosh 连接到 MongoDB3.2 基础操作与 CRUD 4. Python 操作 MongoDB5. Nodejs 操作 MongoDB参考文献 1. 容器与应用之间的关系介绍 MongoDB 的安装有时候并不是那么容易的&#xff0…

C++:模板特化 非类型模板参数

目录 1.非类型模板参数 2.模板特化 2.1 为什么需要模板特化 2.2 函数模板特化 2.3 类模板特化 1.全特化 2.偏特化 1.部分特化 2.参数更进一步的限制 1.非类型模板参数 模板参数分类类型形参与非类型形参 类型形参即&#xff1a;出现在模板参数列表中&#xff0c;跟在 cl…

java正则校验,手机号,邮箱,日期格式,时间格式,数字金额两位小数

java正则校验&#xff0c;手机号&#xff0c;邮箱&#xff0c;日期格式&#xff0c;时间格式&#xff0c;数字金额两位小数 3.58是否为金额&#xff1a;true 3.582是否为金额&#xff1a;false 1284789qq.com是否为email&#xff1a;true 1284789qq.com是否为email&#xff1…

01_Anaconda环境搭建

概述 Anaconda包含了许多常用的科学计算和数据分析的库和工具。通过Anaconda&#xff0c;用户可以更方便地安装、管理和更新这些库和工具&#xff0c;从而提高工作效率。 Anaconda还提供了一个名为conda的包管理器&#xff0c;可以帮助用户方便地安装、管理和更新这些库和工具…

linux 基于科大讯飞的文字转语音使用

官方文档地址&#xff1a;离线语音合成 Linux SDK 文档 | 讯飞开放平台文档中心 一、SDK下载 1、点击上面官方文档地址的链接&#xff0c;可以跳转到以下界面。 2、点击“普通版”&#xff0c;跳转到以下界面。 3、点击“下载”跳转到以下界面 4、最后&#xff0c;点击“SDK下…

AI编译器的前端优化策略

背景 工作领域是AI芯片工具链相关&#xff0c;很多相关知识的概念都是跟着项目成长建立起来&#xff0c;但是比较整个技术体系在脑海中都不太系统&#xff0c;比如项目参与中涉及到了很多AI编译器开发相关内容&#xff0c;东西比较零碎&#xff0c;工作中也没有太多时间去做复盘…

Linux 增加 SWAP 空间

一、需求 通过阿里云启动项目时&#xff0c;使用Vuepress build编译静态页面时内存需要800MB&#xff0c;导致内存不够&#xff0c;因此考虑使用swap方式&#xff0c;置换一些内存资源存放swap磁盘。 [rootxxx myblog]# npm run docs:dev> myblog1.0.0 docs:dev > vuep…

分类预测 | Matlab实现DT决策树多特征分类预测

分类预测 | Matlab实现DT决策树多特征分类预测 目录 分类预测 | Matlab实现DT决策树多特征分类预测分类效果基本描述程序设计参考资料分类效果

ParaView更改RenderView背景颜色

如下图&#xff0c;这种蓝紫色是ParaView的RenderView默认设置颜色 想要更改背景颜色&#xff0c;需要打开Properties如果想要更改渲染物体的颜色&#xff0c;需要打开Color Map Editor 打开方式&#xff1a; 在页面上方工具栏的地方右键&#xff0c;勾选Properties和Color …

stable diffusion学习笔记——文生图(二)

LORA和Embeddings都可以对画面内容进行调整。目前LORA主要用来定义画面特征&#xff0c;如具体的人物&#xff0c;衣物&#xff0c;画风等。Embeddings目前主要用于反面提示词中&#xff0c;用来避免错误的画面表现。 LORA lora的全称为&#xff1a;低秩适应模型。lora的基本…

算法,不再难学!揭秘两款让你迅速学会算法的在线工具

1. VisuAlgo VisuAlgo 是一个由 Dr. Steven Halim 创立的在线平台,用于通过可视化的方式帮助学生和开发者理解和掌握各种复杂的数据结构和算法。该网站特别适合那些视觉学习者,也就是通过看图形、动画和演示来更好地理解概念的人。 以下是 VisuAlgo 的一些关键特点和功能: …

深兰科技入选亿欧《“制”敬不凡先锋榜·智能机器人Top10》榜单

日前&#xff0c;由亿欧协办的2023工博会工业智能化发展高峰论坛于上海成功举办&#xff0c;会上发布了《2023智能制造&#xff1a;“制”敬不凡先锋者》系列名单。深兰科技凭借在智能机器人开发中的技术创新和模式应用&#xff0c;入选《“制”敬不凡先锋榜——智能机器人Top1…