You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go/Gin中会话校验中间件重定向后无法终止执行链

Gin中间件会话校验后仍执行路由处理函数的问题

问题描述

我在Gin框架中编写了CheckSession中间件,用于在请求处理前校验会话有效性。相关路由代码如下:

profile.Use(session.CheckSession())
profile.GET("/:pid", func(c *gin.Context) {
    fmt.Println("Hit :pid")
    c.File("../../html/profile.html")
})

CheckSession中间件代码:

func CheckSession() gin.HandlerFunc {
    return func(c *gin.Context) {
        session := sessions.Default(c)
        userID := session.Get("user_id")
        firstName := session.Get("firstname")
        lastName := session.Get("lastname")

        if userID == nil || firstName == nil || lastName == nil {
            fmt.Println("No session")
            c.Redirect(http.StatusSeeOther, "/sign-in")
            return
        }

        fmt.Println("Hit c.Next()")
        c.Next()
    }
}

实际异常现象:
当访问"/"路由时会重定向到/profile/:pid端点,会话无效时该端点本应重定向到/sign-in,实际跳转确实生效,但/profile/:pid的处理函数仍会执行,且日志显示从未调用c.Next()。即使改用if-else结构确保仅执行重定向或c.Next(),问题依旧存在。


问题原因与解决方法

核心原因

Gin中调用c.Redirect()后直接return,只会退出当前中间件函数,但不会终止整个请求处理链的执行,后续的路由处理函数仍会被触发。必须通过c.Abort()显式中断处理链,才能阻止后续逻辑执行。

修正后的中间件代码

func CheckSession() gin.HandlerFunc {
    return func(c *gin.Context) {
        session := sessions.Default(c)
        userID := session.Get("user_id")
        firstName := session.Get("firstname")
        lastName := session.Get("lastname")

        if userID == nil || firstName == nil || lastName == nil {
            fmt.Println("No session")
            c.Redirect(http.StatusSeeOther, "/sign-in")
            // 调用Abort终止后续所有处理逻辑
            c.Abort()
            return
        }

        fmt.Println("Hit c.Next()")
        c.Next()
    }
}

关键说明

  • c.Abort()会通知Gin停止执行处理链中剩余的中间件和路由处理函数,确保重定向完成后不会再执行/profile/:pid的处理代码。
  • 原代码中仅用return退出中间件,Gin会继续执行链中的下一个环节,这就是重定向生效但处理函数仍运行的根本原因。

内容的提问来源于stack exchange,提问作者Alexsen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 18:55:17