package middleware import ( "ppgo_job/dao" "ppgo_job/libs" "ppgo_job/model/entity" "strings" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/util/gconv" ) // Auth 认证中间件 — 支持 Cookie 和 JWT 双认证 func Auth(r *ghttp.Request) { // 尝试 Cookie 认证(兼容旧模板) if tryCookieAuth(r) { r.Middleware.Next() return } // 尝试 JWT 认证(新前端) if tryJWTAuth(r) { r.Middleware.Next() return } // 都失败 redirectToLogin(r) } // tryJWTAuth 尝试 JWT 认证 func tryJWTAuth(r *ghttp.Request) bool { authHeader := r.Header.Get("Authorization") if authHeader == "" { // 也尝试从 query 参数读取 token authHeader = r.Get("token", "").String() if authHeader == "" { return false } } // 去除 Bearer 前缀 token := strings.TrimPrefix(authHeader, "Bearer ") if token == authHeader { // 没有 Bearer 前缀,去掉也行 } claims, err := libs.ParseJWT(token) if err != nil { return false } // 查询用户是否存在且未被禁用 admin, err := dao.Admin.GetById(r.GetCtx(), claims.UserId) if err != nil || admin == nil || admin.Status != 1 { return false } // 注入用户信息 r.SetCtxVar("userId", admin.Id) r.SetCtxVar("loginUserId", admin.Id) r.SetCtxVar("loginUserName", admin.RealName) r.SetCtxVar("user", admin) // 加载权限 loadPermissions(r, admin) return true } // tryCookieAuth 尝试 Cookie 认证(兼容旧模板) func tryCookieAuth(r *ghttp.Request) bool { authCookie := r.Cookie.Get("auth") if authCookie == nil { return false } authStr := authCookie.String() parts := strings.Split(authStr, "|") if len(parts) != 2 { return false } userId := gconv.Int(parts[0]) hash := parts[1] if userId < 1 || hash == "" { return false } // 查询用户 admin, err := dao.Admin.GetById(r.GetCtx(), userId) if err != nil || admin == nil || admin.Status != 1 { return false } // 验证 hash clientIp := r.GetClientIp() expectedHash := libs.Sha256Hex([]byte(admin.Salt + "|" + clientIp + "|" + admin.Password)) if hash != expectedHash { return false } // 注入用户信息 r.SetCtxVar("userId", admin.Id) r.SetCtxVar("loginUserId", admin.Id) r.SetCtxVar("loginUserName", admin.RealName) r.SetCtxVar("user", admin) // 加载权限 loadPermissions(r, admin) return true } // AuthCheck 权限检查中间件 func AuthCheck(r *ghttp.Request) { userId := r.GetCtxVar("userId", 0).Int() if userId == 0 { redirectToLogin(r) return } r.Middleware.Next() } // loadPermissions 加载权限和菜单 func loadPermissions(r *ghttp.Request, admin *entity.Admin) { ctx := r.GetCtx() // 从角色的权限关联获取可访问的URL var allowUrls []string // 侧边栏菜单 authList, _ := dao.Auth.GetList(ctx, "status", 1) menu1 := make([]g.Map, 0) menu2 := make([]g.Map, 0) for _, v := range authList { if v.Pid == 0 && v.IsShow == 1 { allowUrls = append(allowUrls, v.AuthUrl) menu1 = append(menu1, g.Map{ "Id": v.Id, "Sort": v.Sort, "AuthName": v.AuthName, "AuthUrl": v.AuthUrl, "Icon": v.Icon, "Pid": v.Pid, }) } else if v.Pid != 0 && v.IsShow == 1 { allowUrls = append(allowUrls, v.AuthUrl) menu2 = append(menu2, g.Map{ "Id": v.Id, "Sort": v.Sort, "AuthName": v.AuthName, "AuthUrl": v.AuthUrl, "Icon": v.Icon, "Pid": v.Pid, }) } } r.SetCtxVar("SideMenu1", menu1) r.SetCtxVar("SideMenu2", menu2) r.SetCtxVar("allowUrl", strings.Join(allowUrls, ",")) // 数据权限 roleIds := admin.RoleIds if roleIds == "" || roleIds == "0" || admin.Id == 1 { r.SetCtxVar("serverGroups", "") r.SetCtxVar("taskGroups", "") return } // 非超级管理员,按角色限制数据范围 roleIdArr := strings.Split(roleIds, ",") allServerGroups := make([]string, 0) allTaskGroups := make([]string, 0) for _, rid := range roleIdArr { if id := gconv.Int(rid); id > 0 { role, _ := dao.Role.GetById(ctx, id) if role != nil { if role.ServerGroupIds != "" { allServerGroups = append(allServerGroups, role.ServerGroupIds) } if role.TaskGroupIds != "" { allTaskGroups = append(allTaskGroups, role.TaskGroupIds) } } } } r.SetCtxVar("serverGroups", strings.Join(allServerGroups, ",")) r.SetCtxVar("taskGroups", strings.Join(allTaskGroups, ",")) } func redirectToLogin(r *ghttp.Request) { if r.IsAjaxRequest() { r.Response.WriteJson(g.Map{"status": -1, "message": "请先登录"}) } else { // API 请求也返回 JSON if strings.HasPrefix(r.URL.Path, "/api/") { r.Response.WriteJson(g.Map{"code": 401, "message": "请先登录"}) } else { r.Response.RedirectTo("/") } } r.Exit() }