jwt中间件401但登录成功,主因是token与中间件不匹配:exp必须为int64秒级时间戳、authorization头格式须为“bearer xxx”(无多余空格或前缀错误)、中间件未全局注册导致部分路由绕过鉴权。

JWT 中间件 401 但登录成功的典型原因
不是密钥错了,而是 token 和中间件对不上。最常踩的坑就三个:
-
exp字段用了毫秒时间戳或字符串——必须是int64秒级 Unix 时间戳,比如time.Now().Add(time.Hour).Unix() -
Authorization请求头格式不对:必须是Bearer xxx,前后不能多空格,也不能写成Token xxx或Bearerxxx - 中间件没全局注册:只在
v1 := router.Group("/api/v1")里调了v1.Use(jwtauth.Middleware()),那/api/users这类未分组路由就完全绕过鉴权
菜单数据怎么查才不 N+1、不 panic
菜单通常是树形结构(比如 rule 表里有 parent_id),GORM 默认不会自动加载子项。直接 db.Find(&menus) 再循环取 menu.Children,会触发 N 次 SQL;更糟的是,如果 Menu 结构体里嵌套了 Children []Menu,JSON 序列化时直接无限递归 panic。
- 用
Preload一次性查出整棵树:db.Preload("Children").Where("parent_id = ?", 0).Find(&menus) - 结构体字段必须用指针:
Children []*Menu `gorm:"foreignKey:ParentID"`,禁用嵌套值类型 - JSON 输出时加
json:"children,omitempty"tag,避免空 slice 冗余输出
权限校验中间件怎么写才真正生效
别把权限逻辑塞进每个 handler,中间件才是统一入口。关键是两点:拿到用户角色后,得提前查好该角色能访问哪些菜单/接口,而不是每次请求都查 DB。
- 登录成功后,把角色 ID 和预计算的权限 map(如
map[string]bool{"GET_/api/users": true})一起塞进c.Set("permissions", permMap) - 中间件里用
c.Request.Method + "_" + c.Request.URL.Path拼出权限 key,查 map 判断是否放行 - 超管跳过检查:
if isSuper == 1 { c.Next(); return },别漏掉这个分支
前端动态菜单怎么和后端权限对齐
菜单不是前端硬编码出来的,而是登录后从后端拉取的“带权限标记的树”。后端返回的数据结构必须包含 checked 字段,告诉前端这个菜单节点当前用户是否有权展示。
- 查菜单时,先查所有启用的菜单(
status = 1),再查该用户角色关联的role_access记录 - 用
map[int]bool快速判断某菜单 ID 是否被授权,遍历菜单树时逐个设menu.Checked = roleAccessMap[menu.ID] - 前端收到后只渲染
checked: true的节点,且按钮级权限也靠同一套 map 控制显隐
checked,三者 timestamp 和数据一致性必须对齐,否则会出现“刚授予权限却看不到菜单”的现象。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











