gin.basicauth()不能用于登录拦截,因其强制弹窗、明文传输、无法自定义页面或跳转;应使用session或jwt中间件实现可控鉴权与重定向。

为什么 gin.BasicAuth() 不能直接用在登录拦截上
因为 gin.BasicAuth() 是 HTTP Basic Auth 协议实现,它会强制浏览器弹出认证框、明文 base64 编码传输密码,且无法自定义登录页或跳转逻辑——这和常规 Web 登录完全不是一回事。真正需要的是基于 session 或 token 的中间件式拦截,由你控制登录态校验、重定向和响应体。
用 gin.HandlerFunc 写一个带 session 校验的登录拦截器
Gin 本身不内置 session 支持,得靠第三方库(比如 github.com/gin-contrib/sessions)配合。核心思路是:检查 session 中是否存在 user_id 或 logged_in 字段,不存在就重定向到 /login;存在才放行。
- 先引入 session 中间件:
store := sessions.NewCookieStore([]byte("secret")),密钥别硬编码进生产环境 - 在路由前注册:
r.Use(sessions.Sessions("mysession", store)) - 拦截器里取 session:
session := sessions.Default(c),再调session.Get("user_id") - 注意:如果用 Redis Store,
session.Save()不是必须的,但 Cookie Store 下修改后需显式调用 - 重定向用
c.Redirect(http.StatusFound, "/login"),别用http.StatusMovedPermanently
拦截器怎么区分「登录页」和「需登录接口」
别把拦截器全局挂载(r.Use(authMiddleware)),否则连 /login 和 /static/ 都被拦了。要用分组路由精准控制范围:
-
auth := r.Group("/")—— 这里放首页、仪表盘等需登录页面 -
api := r.Group("/api")—— 放 JSON 接口,可单独加auth.Use(authMiddleware) -
public := r.Group("")—— 显式放/login、/logout、/health等无需鉴权的路由 - 特别注意:静态资源路径如
/assets/*filepath必须放在拦截器之前注册,否则 404
Token 方案下如何避免重复解析 JWT
如果用 JWT(比如 github.com/golang-jwt/jwt/v5),拦截器里每次都要解析 token 并验证签名、过期时间。高频请求下这是性能瓶颈,而且容易漏掉 kid 或时钟偏移校验。
- 用
c.Set("user", user)把解析后的用户信息缓存到上下文,后续 handler 直接c.MustGet("user").(*User) - 别在拦截器里做数据库查用户——JWT payload 里应已含必要字段(如
uid,role),查库逻辑留给业务 handler 按需触发 - 错误处理要细:token 过期返回
401,格式错误返回400,签名失败返回401,别全塞成 401 - 测试时容易忽略:浏览器发 OPTIONS 预检请求,拦截器里要
c.Next()放行,否则 CORS 失败











