session固定漏洞的本质是攻击者预先获取合法未认证session id并诱导用户登录,服务端未在认证后更换id,致攻击者凭原id直接接管已认证会话。

Session固定漏洞的本质是会话ID复用
攻击者先获取一个合法但未认证的Session ID(比如访问登录页时服务器生成的),然后诱使用户用这个ID登录,登录后服务端不更新Session ID,导致攻击者凭原ID直接获得已认证会话。Gin本身不内置Session管理,所以漏洞是否发生,取决于你用的Session中间件是否在登录成功后调用session.Save()前重生成ID。
gorilla/sessions必须手动调用session.Options.MaxAge = 0并重置ID
使用gorilla/sessions时,默认不会自动刷新Session ID。登录成功后若只改session.Values而不干预ID,就中招。
- 登录成功后,先调用
session.Options.MaxAge = 0让旧Cookie立即失效 - 再调用
session.ID()无法强制更换——它只读;必须用store.NewSession(r, "session-name")新建一个会话实例 - 或者更稳妥:调用
session.Clear()+session.Options.MaxAge = -1彻底清除旧会话,再设新值 - 最后务必调用
session.Save(r, w),否则变更不落地
gin-contrib/sessions的Options.RegenerateID不是默认开启的
gin-contrib/sessions提供了RegenerateID选项,但它默认为false,且仅在中间件初始化时生效,不能动态开关。这意味着即使你配置了RegenerateID: true,它也只在每次请求进入中间件时检查是否需要刷新——但登录逻辑通常绕过该检查。
- 不要依赖
RegenerateID: true自动防御Session固定 - 必须在登录成功路径里显式调用
c.Session().RegenerateID()(如果版本支持)或手动销毁+重建 - 验证方法:抓包看两次登录请求的
Set-Cookie头中session-id是否变化
JWT替代方案能绕过Session固定,但不等于零风险
用JWT做会话管理时,服务端不存储Session ID,自然不存在“固定ID被复用”的问题。但要注意:
- JWT本身需防泄露——不能存在
localStorage,应存于httpOnlyCookie - 登录接口返回JWT时,必须同时清空旧Cookie(如
c.SetCookie("jwt", "", -1, "/", "example.com", true, true)) - 前端若缓存了旧Token并在后续请求中重复发送,而服务端未校验
jti或黑名单机制,仍可能被重放
Session固定漏洞的修复关键不在框架选型,而在登录成功那一刻是否主动切断旧会话链路——无论用Cookie、Session还是JWT,这一步漏掉,防线就塌了一半。











