/* * @desc:中间件 * @company:云南奇讯科技有限公司 * @Author: yixiaohu * @Date: 2022/9/23 15:05 */ package middleware import ( "fmt" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/os/gctx" "github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/util/gconv" "github.com/tiger1103/gfast-token/gftoken" "github.com/tiger1103/gfast/v3/api/wxApplet/wxApplet" commonService "github.com/tiger1103/gfast/v3/internal/app/common/service" "github.com/tiger1103/gfast/v3/internal/app/system/dao" "github.com/tiger1103/gfast/v3/internal/app/system/model" "github.com/tiger1103/gfast/v3/internal/app/system/service" "github.com/tiger1103/gfast/v3/library/libResponse" "strings" ) func init() { service.RegisterMiddleware(New()) } func New() *sMiddleware { return &sMiddleware{} } type sMiddleware struct{} // Ctx 自定义上下文对象 func (s *sMiddleware) Ctx(r *ghttp.Request) { ctx := r.GetCtx() // 初始化登录用户信息 data, err := service.GfToken().ParseToken(r) if err != nil { // 执行下一步请求逻辑 r.Middleware.Next() } if data != nil { context := new(model.Context) err = gconv.Struct(data.Data, &context.User) if err != nil { g.Log().Error(ctx, err) // 执行下一步请求逻辑 r.Middleware.Next() } service.Context().Init(r, context) } // 执行下一步请求逻辑 r.Middleware.Next() } // Auth 权限判断处理中间件 func (s *sMiddleware) Auth(r *ghttp.Request) { ctx := r.GetCtx() //获取登陆用户id adminId := service.Context().GetUserId(ctx) accessParams := r.Get("accessParams").Strings() accessParamsStr := "" if len(accessParams) > 0 && accessParams[0] != "undefined" { accessParamsStr = "?" + gstr.Join(accessParams, "&") } url := gstr.TrimLeft(r.Request.URL.Path, "/") + accessParamsStr /*if r.Method != "GET" && adminId != 1 && url!="api/v1/system/login" { libResponse.FailJson(true, r, "对不起!演示系统,不能删改数据!") }*/ //获取无需验证权限的用户id tagSuperAdmin := false service.SysUser().NotCheckAuthAdminIds(ctx).Iterator(func(v interface{}) bool { if gconv.Uint64(v) == adminId { tagSuperAdmin = true return false } return true }) if tagSuperAdmin { r.Middleware.Next() //不要再往后面执行 return } //获取地址对应的菜单id menuList, err := service.SysAuthRule().GetMenuList(ctx) if err != nil { g.Log().Error(ctx, err) libResponse.FailJson(true, r, "请求数据失败") } var menu *model.SysAuthRuleInfoRes for _, m := range menuList { ms := gstr.SubStr(m.Name, 0, gstr.Pos(m.Name, "?")) if m.Name == url || ms == url { menu = m break } } //只验证存在数据库中的规则 if menu != nil { //若是不登录能访问的接口则不判断权限 excludePaths := g.Cfg().MustGet(ctx, "gfToken.excludePaths").Strings() for _, p := range excludePaths { if gstr.Equal(menu.Name, gstr.TrimLeft(p, "/")) { r.Middleware.Next() return } } //若存在不需要验证的条件则跳过 if gstr.Equal(menu.Condition, "nocheck") { r.Middleware.Next() return } menuId := menu.Id //菜单没存数据库不验证权限 if menuId != 0 { //判断权限操作 enforcer, err := commonService.CasbinEnforcer(ctx) if err != nil { g.Log().Error(ctx, err) libResponse.FailJson(true, r, "获取权限失败") } hasAccess := false hasAccess, err = enforcer.Enforce(fmt.Sprintf("%s%d", service.SysUser().GetCasBinUserPrefix(), adminId), gconv.String(menuId), "All") if err != nil { g.Log().Error(ctx, err) libResponse.FailJson(true, r, "判断权限失败") } if !hasAccess { libResponse.FailJson(true, r, "没有访问权限") } } } else if menu == nil && accessParamsStr != "" { libResponse.FailJson(true, r, "没有访问权限") } r.Middleware.Next() } // Blacklist 黑名单 阻挡小程序的黑名单用户登录 func (s *sMiddleware) Blacklist(r *ghttp.Request) { ctx := gctx.New() //1、判断是否是小程序请求来的数据 userAgent := strings.ToLower(r.Header.Get("User-Agent")) if strings.Contains(userAgent, "micromessenger") { //2、解析token 拿到openid var user *wxApplet.BusConstructionUserAddReq datatoken, err := service.GfToken().ParseToken(r) if err != nil { libResponse.FailJson(true, r, "解析token错误!") } if datatoken != nil { err = gconv.Struct(datatoken.Data, &user) if err != nil { libResponse.FailJson(true, r, "获取用户信息错误!") } } //3、查询数据库黑名单 count, err := dao.BusConstructionBlacklist.Ctx(ctx).Where("openid", user.Openid).Count() if err != nil { libResponse.FailJson(true, r, "系统错误,请联系管理员!") } if count > 0 { gfToken := gftoken.NewGfToken() token := gfToken.GetRequestToken(r) service.GfToken().RemoveToken(ctx, token) libResponse.FailJson(true, r, "登录异常,请联系管理员!") } else { //4、匹配黑名单用户 随后放行 r.Middleware.Next() } } else { r.Middleware.Next() } } var engineeringData = "/zm/api/v1/system/documentData/newFolder," + //新建文件夹 "/zm/api/v1/system/documentData/add," + //导入 "/zm/api/v1/system/documentData/edit" + //重命名 "/zm/api/v1/system/documentData/compressedDownload" + //下载 "/zm/api/v1/system/documentData/get" + //查看 "/zm/api/v1/system/documentData/complaintBoxAdd" + //保存 "/zm/api/v1/system/documentData/delete" + //删除 "/zm/api/v1/system/documentData/onlineImport" + //模板批量导入 "/zm/api/v1/system/documentData/onlineMobile" + //资料在线移动 "/zm/api/v1/system/documentData/dataFileQuery" + //所有资料查询 "/zm/api/v1/system/document/templateRecycleBin" + //模板回收站 "/zm/api/v1/system/documentData/dataRecyclingStation" + //资料回收站 "/zm/api/v1/system/documentData/uniFileDownload" //下载 // EngineeringDataPermission 工程资料权限校验(资料-回收站) func (s *sMiddleware) EngineeringDataPermission(r *ghttp.Request) { ctx := r.GetCtx() userId := service.Context().GetUserId(ctx) //0、把admin用户给排除掉 if userId == 1 { r.Middleware.Next() return } projectId := r.Get("projectId").String() //1、看看有哪些API需要调用权限 path := r.Request.URL.Path authorityJudgment := strings.Split(engineeringData, ",") for _, pathApi := range authorityJudgment { //2、根据用户id去数据库查询工程资料的权限是否开启(1有权 2无权) if pathApi == path { if projectId == "" { libResponse.FailJson(true, r, "当前操作暂无项目id!") } sql := g.DB().Model("document_power"). Where("sys_user_id", userId). Where("project_id", projectId) if strings.Contains(path, "/zm/api/v1/system/document/allList") || strings.Contains(path, "/zm/api/v1/system/documentData/allList") { sql = sql.Where("type = 3") } else if strings.Contains(path, "/zm/api/v1/system/documentData/") { sql = sql.Where("type = 2") } else { libResponse.FailJson(true, r, "系统错误,请联系管理员!") } //3、判断具体是什么权限 fetch := fieldFetch(path, authorityJudgment) count, err := sql.Where(fetch, "1").Count() if err != nil { libResponse.FailJson(true, r, "系统错误,请联系管理员!") } if count > 0 { r.Middleware.Next() } else { libResponse.FailJson(true, r, "当前操作暂无权限!") } } } r.Middleware.Next() } // fieldFetch 根据数据匹配 返回需要查询的字段 func fieldFetch(path string, authorityJudgment []string) string { switch path { case authorityJudgment[0]: return "v1" case authorityJudgment[1]: return "v2" case authorityJudgment[2]: return "v3" case authorityJudgment[3]: return "v4" case authorityJudgment[4]: return "v5" case authorityJudgment[5]: return "v6" case authorityJudgment[6]: return "v7" case authorityJudgment[7]: return "v8" case authorityJudgment[8]: return "v9" case authorityJudgment[9]: return "v10" case authorityJudgment[10]: return "v11" case authorityJudgment[11]: return "v12" case authorityJudgment[12]: return "v4" default: return "" } }