不能只靠 Cookie 存在与否做授权判断,因为 Cookie 可被攻击者伪造,真正的授权依据是服务端存储并校验的 session 数据,需通过中间件实时验证其真实性、有效性与权限。

为什么不能只靠 Cookie 存在与否做授权判断
直接检查 c.Cookie("session_id") 是否返回 nil 或报错 http.ErrNoCookie,只能说明客户端没发 Cookie,不代表身份合法。攻击者可伪造任意 Cookie 值(如 session_id=abc123)发起请求,而你的代码若没校验该值是否真实签发、是否过期、是否被吊销,就等于开门揖盗。
必须配合 Session 中间件和后端存储做实时校验
Cookie 本身只是 session ID 的传输载体,真正的授权依据是服务端存储的 session 数据。Echo 不内置 session 管理,必须显式注册 session.Middleware() 并指定后端(如 Redis 或文件系统)。常见疏漏点:
- 只 import
github.com/labstack/echo-contrib/session,但没调用e.Use(session.Middleware(...))—— 此时session.FromContext(c.Request().Context())返回nil - Session 存储密钥太短(如
"123"),导致 AES 加解密失败,sess.Values读出来是空或 panic - 没校验
sess.Options.MaxAge和客户端Cookie.MaxAge是否协同:前者控制服务端数据过期,后者控制浏览器何时自动删除 Cookie;两者不一致会导致“用户已登出但 Cookie 还在”或“用户仍登录但服务端已删 session”
拦截逻辑应放在中间件里,且早于业务 handler 执行
授权检查必须在请求进入路由前完成,否则业务逻辑可能已执行副作用(如扣款、发邮件)。正确写法是自定义中间件,在其中提取并验证 session:
func AuthCookieMiddleware() echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
sess, err := session.Get("user_session", c)
if err != nil {
return c.NoContent(http.StatusForbidden) // 或重定向登录页
}
// 检查 session 是否有有效用户标识
if _, ok := sess.Values["user_id"]; !ok {
return c.NoContent(http.StatusUnauthorized)
}
// 可选:检查权限字段,如 role == "admin"
if role, ok := sess.Values["role"].(string); ok && role != "admin" {
return c.NoContent(http.StatusForbidden)
}
return next(c)
}
}
}
注意:sess.Values["user_id"] 是 interface{},必须先判空再类型断言,否则运行时 panic。
敏感操作必须双重校验:Cookie + 请求上下文特征
仅依赖 Cookie 的 session ID 仍有风险(如 XSS 窃取、CSRF 滥用)。对高危操作(如修改密码、转账),应叠加校验:
- 比对
c.Request().Header.Get("User-Agent")或IP是否与登录时记录一致(需 session 存储这些字段) - 要求二次认证:检查
c.Request().Header.Get("X-2FA-Token")是否匹配当前 session 绑定的 TOTP - 拒绝来自非同源(
Origin)的带 Cookie 请求,尤其当AllowCredentials: true开启时 —— 否则 CSRF 防护形同虚设
真正难处理的不是“怎么读 Cookie”,而是“怎么确认这个 Cookie 此刻代表一个可信、未被劫持、且具备当前操作权限的会话”。所有校验必须发生在 c.Request().Body 被读取前,且不能依赖任何后续 handler 才初始化的状态。











