package mid import ( "fmt" "log" "net/http" "time" "management/internal/erpserver/model/dto" v1 "management/internal/erpserver/service/v1" "management/internal/pkg/know" "management/internal/pkg/session" "github.com/patrickmn/go-cache" ) var publicRoutes = map[string]bool{ "/home.html": true, "/dashboard": true, "/system/menus": true, "/upload/img": true, "/upload/file": true, "/upload/multi_files": true, "/pear.json": true, "/logout": true, } // 定义一个全局的go-cache实例 var menuCache *cache.Cache func init() { // 初始化go-cache,设置默认过期时间为5分钟,每10分钟清理一次过期项 menuCache = cache.New(5*time.Minute, 10*time.Minute) } func Authorize( sess session.Manager, menuService v1.MenuService, ) func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ctx := r.Context() path := r.URL.Path // 登陆检查 user, err := sess.GetUser(ctx, know.StoreName) if err != nil || user.ID == 0 { http.Redirect(w, r, "/", http.StatusFound) return } // 公共路由放行 if publicRoutes[path] { ctx = setUser(ctx, user) next.ServeHTTP(w, r.WithContext(ctx)) return } n1 := time.Now() // 权限检查 var menus map[string]*dto.OwnerMenuDto cacheKey := fmt.Sprintf("user_menus:%d", user.RoleID) // 使用用户RoleID作为缓存key // 尝试从内存缓存中获取菜单数据 if cachedMenus, found := menuCache.Get(cacheKey); found { menus = cachedMenus.(map[string]*dto.OwnerMenuDto) log.Printf("listByRoleIDToMap (from cache): %s", time.Since(n1).String()) } else { // 内存缓存未命中,从menuService获取,并存入内存缓存 menus, err = menuService.ListByRoleIDToMap(ctx, user.RoleID) if err != nil { http.Error(w, "Forbidden", http.StatusForbidden) return } menuCache.Set(cacheKey, menus, cache.DefaultExpiration) // 使用默认过期时间 log.Printf("listByRoleIDToMap (from service, then cached): %s", time.Since(n1).String()) } if !hasPermission(menus, path) { http.Error(w, "Forbidden", http.StatusForbidden) return } cur := getCurrentMenus(menus, path) ctx = setUser(ctx, user) ctx = setCurMenus(ctx, cur) next.ServeHTTP(w, r.WithContext(ctx)) }) } } func hasPermission(menus map[string]*dto.OwnerMenuDto, path string) bool { _, ok := menus[path] return ok } func getCurrentMenus(data map[string]*dto.OwnerMenuDto, path string) []dto.OwnerMenuDto { var res []dto.OwnerMenuDto menu, ok := data[path] if !ok { return res } for _, item := range data { if menu.IsList { if item.ParentID == menu.ID || item.ID == menu.ID { res = append(res, *item) } } else { if item.ParentID == menu.ParentID { res = append(res, *item) } } } return res }