Files
zmkgC/internal/app/system/logic/middleware/middleware.go
2025-07-07 20:11:59 +08:00

271 lines
8.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* @desc:中间件
* @company:云南奇讯科技有限公司
* @Author: yixiaohu<yxh669@qq.com>
* @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 ""
}
}