Преглед изворни кода

权限判断修复,缓存优化,登录优化

yxh пре 4 година
родитељ
комит
06fa50979a

+ 29 - 0
api/v1/system/sys_login.go

@@ -0,0 +1,29 @@
+/*
+* @desc:登录
+* @company:云南奇讯科技有限公司
+* @Author: yixiaohu
+* @Date:   2022/4/27 21:51
+ */
+
+package system
+
+import (
+	"github.com/gogf/gf/v2/frame/g"
+	"github.com/tiger1103/gfast/v3/internal/app/system/model"
+)
+
+type UserLoginReq struct {
+	g.Meta     `path:"/login" tags:"登录" method:"post" summary:"用户登录"`
+	Username   string `p:"username" v:"required#用户名不能为空"`
+	Password   string `p:"password" v:"required#密码不能为空"`
+	VerifyCode string `p:"verifyCode" v:"required#验证码不能为空"`
+	VerifyKey  string `p:"verifyKey"`
+}
+
+type UserLoginRes struct {
+	g.Meta      `mime:"application/json"`
+	UserInfo    *model.LoginUserRes `json:"userInfo"`
+	Token       string              `json:"token"`
+	MenuList    []*model.UserMenus  `json:"menuList"`
+	Permissions []string            `json:"permissions"`
+}

+ 1 - 17
api/v1/system/sys_user.go

@@ -7,24 +7,8 @@ import (
 	"github.com/tiger1103/gfast/v3/internal/app/system/model/entity"
 )
 
-type UserLoginReq struct {
-	g.Meta     `path:"/login" tags:"登录" method:"post" summary:"用户登录"`
-	Username   string `p:"username" v:"required#用户名不能为空"`
-	Password   string `p:"password" v:"required#密码不能为空"`
-	VerifyCode string `p:"verifyCode" v:"required#验证码不能为空"`
-	VerifyKey  string `p:"verifyKey"`
-}
-
-type UserLoginRes struct {
-	g.Meta      `mime:"application/json"`
-	UserInfo    *model.LoginUserRes `json:"userInfo"`
-	Token       string              `json:"token"`
-	MenuList    []*model.UserMenus  `json:"menuList"`
-	Permissions []string            `json:"permissions"`
-}
-
 type UserMenusReq struct {
-	g.Meta        `path:"/user/getUserMenus" tags:"登录" method:"get" summary:"获取用户菜单"`
+	g.Meta        `path:"/user/getUserMenus" tags:"用户管理" method:"get" summary:"获取用户菜单"`
 	Authorization string `p:"Authorization" in:"header" dc:"Bearer {{token}}"`
 }
 

+ 96 - 0
internal/app/system/controller/sys_login.go

@@ -0,0 +1,96 @@
+/*
+* @desc:登录
+* @company:云南奇讯科技有限公司
+* @Author: yixiaohu
+* @Date:   2022/4/27 21:52
+ */
+
+package controller
+
+import (
+	"context"
+	"github.com/gogf/gf/v2/crypto/gmd5"
+	"github.com/gogf/gf/v2/errors/gerror"
+	"github.com/gogf/gf/v2/frame/g"
+	"github.com/gogf/gf/v2/util/gconv"
+	"github.com/gogf/gf/v2/util/gmode"
+	"github.com/tiger1103/gfast/v3/api/v1/system"
+	commonService "github.com/tiger1103/gfast/v3/internal/app/common/service"
+	"github.com/tiger1103/gfast/v3/internal/app/system/model"
+	"github.com/tiger1103/gfast/v3/internal/app/system/service"
+	"github.com/tiger1103/gfast/v3/library/libUtils"
+)
+
+var (
+	Login = loginController{}
+)
+
+type loginController struct {
+	BaseController
+}
+
+func (c *loginController) Login(ctx context.Context, req *system.UserLoginReq) (res *system.UserLoginRes, err error) {
+	var (
+		user        *model.LoginUserRes
+		token       string
+		permissions []string
+		menuList    []*model.UserMenus
+	)
+	//判断验证码是否正确
+	debug := gmode.IsDevelop()
+	if !debug {
+		if !commonService.Captcha().VerifyString(req.VerifyKey, req.VerifyCode) {
+			err = gerror.New("验证码输入错误")
+			return
+		}
+	}
+	ip := libUtils.GetClientIp(ctx)
+	userAgent := libUtils.GetUserAgent(ctx)
+	user, err = service.User().GetAdminUserByUsernamePassword(ctx, req)
+	if err != nil {
+		// 保存登录失败的日志信息
+		service.SysLoginLog().Invoke(ctx, &model.LoginLogParams{
+			Status:    0,
+			Username:  req.Username,
+			Ip:        ip,
+			UserAgent: userAgent,
+			Msg:       err.Error(),
+			Module:    "系统后台",
+		})
+		return
+	}
+	err = service.User().UpdateLoginInfo(ctx, user.Id, ip)
+	if err != nil {
+		return
+	}
+	// 报存登录成功的日志信息
+	service.SysLoginLog().Invoke(ctx, &model.LoginLogParams{
+		Status:    1,
+		Username:  req.Username,
+		Ip:        ip,
+		UserAgent: userAgent,
+		Msg:       "登录成功",
+		Module:    "系统后台",
+	})
+	key := gconv.String(user.Id) + "-" + gmd5.MustEncryptString(user.UserName) + gmd5.MustEncryptString(user.UserPassword)
+	if g.Cfg().MustGet(ctx, "gfToken.multiLogin").Bool() {
+		key = gconv.String(user.Id) + "-" + gmd5.MustEncryptString(user.UserName) + gmd5.MustEncryptString(user.UserPassword+ip+userAgent)
+	}
+	user.UserPassword = ""
+	token, err = service.GfToken().GenerateToken(ctx, key, user)
+	if err != nil {
+		return
+	}
+	//获取用户菜单数据
+	menuList, permissions, err = service.User().GetAdminRules(ctx, user.Id)
+	if err != nil {
+		return
+	}
+	res = &system.UserLoginRes{
+		UserInfo:    user,
+		Token:       token,
+		MenuList:    menuList,
+		Permissions: permissions,
+	}
+	return
+}

+ 0 - 73
internal/app/system/controller/sys_user.go

@@ -2,17 +2,10 @@ package controller
 
 import (
 	"context"
-	"github.com/gogf/gf/v2/crypto/gmd5"
-	"github.com/gogf/gf/v2/errors/gerror"
-	"github.com/gogf/gf/v2/frame/g"
-	"github.com/gogf/gf/v2/util/gconv"
-	"github.com/gogf/gf/v2/util/gmode"
 	"github.com/tiger1103/gfast/v3/api/v1/system"
-	commonService "github.com/tiger1103/gfast/v3/internal/app/common/service"
 	"github.com/tiger1103/gfast/v3/internal/app/system/model"
 	"github.com/tiger1103/gfast/v3/internal/app/system/model/entity"
 	"github.com/tiger1103/gfast/v3/internal/app/system/service"
-	"github.com/tiger1103/gfast/v3/library/libUtils"
 )
 
 var (
@@ -23,72 +16,6 @@ type userController struct {
 	BaseController
 }
 
-func (c *userController) Login(ctx context.Context, req *system.UserLoginReq) (res *system.UserLoginRes, err error) {
-	var (
-		user        *model.LoginUserRes
-		token       string
-		permissions []string
-		menuList    []*model.UserMenus
-	)
-	//判断验证码是否正确
-	debug := gmode.IsDevelop()
-	if !debug {
-		if !commonService.Captcha().VerifyString(req.VerifyKey, req.VerifyCode) {
-			err = gerror.New("验证码输入错误")
-			return
-		}
-	}
-	ip := libUtils.GetClientIp(ctx)
-	userAgent := libUtils.GetUserAgent(ctx)
-	user, err = service.User().GetAdminUserByUsernamePassword(ctx, req)
-	if err != nil {
-		// 保存登录失败的日志信息
-		service.SysLoginLog().Invoke(ctx, &model.LoginLogParams{
-			Status:    0,
-			Username:  req.Username,
-			Ip:        ip,
-			UserAgent: userAgent,
-			Msg:       err.Error(),
-			Module:    "系统后台",
-		})
-		return
-	}
-	err = service.User().UpdateLoginInfo(ctx, user.Id, ip)
-	if err != nil {
-		return
-	}
-	// 报存登录成功的日志信息
-	service.SysLoginLog().Invoke(ctx, &model.LoginLogParams{
-		Status:    1,
-		Username:  req.Username,
-		Ip:        ip,
-		UserAgent: userAgent,
-		Msg:       "登录成功",
-		Module:    "系统后台",
-	})
-	key := gconv.String(user.Id) + "-" + gmd5.MustEncryptString(user.UserName) + gmd5.MustEncryptString(user.UserPassword)
-	if g.Cfg().MustGet(ctx, "gfToken.multiLogin").Bool() {
-		key = gconv.String(user.Id) + "-" + gmd5.MustEncryptString(user.UserName) + gmd5.MustEncryptString(user.UserPassword+ip+userAgent)
-	}
-	user.UserPassword = ""
-	token, err = service.GfToken().GenerateToken(ctx, key, user)
-	if err != nil {
-		return
-	}
-	//获取用户菜单数据
-	menuList, permissions, err = service.User().GetAdminRules(ctx, user.Id)
-	if err != nil {
-		return
-	}
-	res = &system.UserLoginRes{
-		UserInfo:    user,
-		Token:       token,
-		MenuList:    menuList,
-		Permissions: permissions,
-	}
-	return
-}
-
 // GetUserMenus 获取用户菜单及按钮权限
 func (c *userController) GetUserMenus(ctx context.Context, req *system.UserMenusReq) (res *system.UserMenusRes, err error) {
 	var (

+ 4 - 0
internal/app/system/router/router.go

@@ -21,6 +21,10 @@ func BindController(group *ghttp.RouterGroup) {
 		group.Bind(
 			controller.DbInit,
 		)
+		group.Bind(
+			//登录
+			controller.Login,
+		)
 		//登录验证拦截
 		service.GfToken().Middleware(group)
 		//context拦截器

+ 5 - 10
internal/app/system/service/middleware.go

@@ -8,6 +8,7 @@
 package service
 
 import (
+	"fmt"
 	"github.com/gogf/gf/v2/frame/g"
 	"github.com/gogf/gf/v2/net/ghttp"
 	"github.com/gogf/gf/v2/text/gstr"
@@ -111,17 +112,11 @@ func (s *middlewareImpl) Auth(r *ghttp.Request) {
 				g.Log().Error(ctx, err)
 				libResponse.FailJson(true, r, "获取权限失败")
 			}
-			groupPolicy := enforcer.GetFilteredGroupingPolicy(0,
-				gconv.String(adminId))
-			if len(groupPolicy) == 0 {
-				libResponse.FailJson(true, r, "没有访问权限")
-			}
 			hasAccess := false
-			for _, v := range groupPolicy {
-				if enforcer.HasPolicy(v[1], gconv.String(menuId), "All") {
-					hasAccess = true
-					break
-				}
+			hasAccess, err = enforcer.Enforce(fmt.Sprintf("%s%d", userService.CasBinUserPrefix, adminId), gconv.String(menuId), "All")
+			if err != nil {
+				g.Log().Error(ctx, err)
+				libResponse.FailJson(true, r, "判断权限失败")
 			}
 			if !hasAccess {
 				libResponse.FailJson(true, r, "没有访问权限")

+ 3 - 3
internal/app/system/service/sys_auth_rule.go

@@ -153,7 +153,7 @@ func (s *ruleImpl) Add(ctx context.Context, req *system.RuleAddReq) (err error)
 	})
 	if err == nil {
 		// 删除相关缓存
-		commonService.Cache().RemoveByTag(ctx, consts.CacheSysAuthTag)
+		commonService.Cache().Remove(ctx, consts.CacheSysAuthMenu)
 	}
 	return
 }
@@ -241,7 +241,7 @@ func (s *ruleImpl) Update(ctx context.Context, req *system.RuleUpdateReq) (err e
 	})
 	if err == nil {
 		// 删除相关缓存
-		commonService.Cache().RemoveByTag(ctx, consts.CacheSysAuthTag)
+		commonService.Cache().Remove(ctx, consts.CacheSysAuthMenu)
 	}
 	return
 }
@@ -307,7 +307,7 @@ func (s *ruleImpl) DeleteMenuByIds(ctx context.Context, ids []int) (err error) {
 				liberr.ErrIsNil(ctx, err)
 			}
 			// 删除相关缓存
-			commonService.Cache().RemoveByTag(ctx, consts.CacheSysAuthTag)
+			commonService.Cache().Remove(ctx, consts.CacheSysAuthMenu)
 		})
 	})
 	return

+ 3 - 3
internal/app/system/service/sys_dept.go

@@ -95,7 +95,7 @@ func (s *deptImpl) Add(ctx context.Context, req *system.DeptAddReq) (err error)
 		})
 		liberr.ErrIsNil(ctx, err, "添加部门失败")
 		// 删除缓存
-		commonService.Cache().RemoveByTag(ctx, consts.CacheSysAuthTag)
+		commonService.Cache().Remove(ctx, consts.CacheSysDept)
 	})
 	return
 }
@@ -115,7 +115,7 @@ func (s *deptImpl) Edit(ctx context.Context, req *system.DeptEditReq) (err error
 		})
 		liberr.ErrIsNil(ctx, err, "修改部门失败")
 		// 删除缓存
-		commonService.Cache().RemoveByTag(ctx, consts.CacheSysAuthTag)
+		commonService.Cache().Remove(ctx, consts.CacheSysDept)
 	})
 	return
 }
@@ -134,7 +134,7 @@ func (s *deptImpl) Delete(ctx context.Context, id int64) (err error) {
 		_, err = dao.SysDept.Ctx(ctx).Where(dao.SysDept.Columns().DeptId+" in (?)", ids).Delete()
 		liberr.ErrIsNil(ctx, err, "删除部门失败")
 		// 删除缓存
-		commonService.Cache().RemoveByTag(ctx, consts.CacheSysAuthTag)
+		commonService.Cache().Remove(ctx, consts.CacheSysDept)
 	})
 	return
 }

+ 6 - 4
internal/app/system/service/sys_role.go

@@ -123,8 +123,8 @@ func (s *roleImpl) AddRole(ctx context.Context, req *system.RoleAddReq) (err err
 			//添加角色权限
 			e = s.AddRoleRule(ctx, req.MenuIds, roleId)
 			liberr.ErrIsNil(ctx, e)
-			//清除TAG缓存
-			commonService.Cache().RemoveByTag(ctx, consts.CacheSysAuthTag)
+			//清除缓存
+			commonService.Cache().Remove(ctx, consts.CacheSysRole)
 		})
 		return err
 	})
@@ -170,8 +170,8 @@ func (s *roleImpl) EditRole(ctx context.Context, req *system.RoleEditReq) (err e
 			//添加角色权限
 			e = s.AddRoleRule(ctx, req.MenuIds, req.Id)
 			liberr.ErrIsNil(ctx, e)
-			//清除TAG缓存
-			commonService.Cache().RemoveByTag(ctx, consts.CacheSysAuthTag)
+			//清除缓存
+			commonService.Cache().Remove(ctx, consts.CacheSysRole)
 		})
 		return err
 	})
@@ -189,6 +189,8 @@ func (s *roleImpl) DeleteByIds(ctx context.Context, ids []int64) (err error) {
 				err = s.DelRoleRule(ctx, v)
 				liberr.ErrIsNil(ctx, err)
 			}
+			//清除缓存
+			commonService.Cache().Remove(ctx, consts.CacheSysRole)
 		})
 		return err
 	})

+ 12 - 8
internal/app/system/service/sys_user.go

@@ -46,11 +46,15 @@ type IUser interface {
 	Delete(ctx context.Context, ids []int) (err error)
 }
 
-type userImpl struct{}
+type userImpl struct {
+	CasBinUserPrefix string //CasBin 用户id前缀
+}
 
 var (
 	notCheckAuthAdminIds *gset.Set //无需验证权限的用户id
-	userService          = userImpl{}
+	userService          = userImpl{
+		CasBinUserPrefix: "u_",
+	}
 )
 
 func User() IUser {
@@ -193,7 +197,7 @@ func (s *userImpl) GetAdminRoleIds(ctx context.Context, userId uint64) (roleIds
 		return
 	}
 	//查询关联角色规则
-	groupPolicy := enforcer.GetFilteredGroupingPolicy(0, gconv.String(userId))
+	groupPolicy := enforcer.GetFilteredGroupingPolicy(0, fmt.Sprintf("%s%d", s.CasBinUserPrefix, userId))
 	if len(groupPolicy) > 0 {
 		roleIds = make([]uint, len(groupPolicy))
 		//得到角色id的切片
@@ -229,7 +233,7 @@ func (s *userImpl) GetAdminMenusByRoleIds(ctx context.Context, roleIds []uint) (
 		menuIds := map[int64]int64{}
 		for _, roleId := range roleIds {
 			//查询当前权限
-			gp := enforcer.GetFilteredPolicy(0, fmt.Sprintf("%d", roleId))
+			gp := enforcer.GetFilteredPolicy(0, gconv.String(roleId))
 			for _, p := range gp {
 				mid := gconv.Int64(p[1])
 				menuIds[mid] = mid
@@ -483,7 +487,7 @@ func (s *userImpl) addUserRole(ctx context.Context, roleIds []int64, userId int6
 		enforcer, e := commonService.CasbinEnforcer(ctx)
 		liberr.ErrIsNil(ctx, e)
 		for _, v := range roleIds {
-			_, e = enforcer.AddGroupingPolicy(gconv.String(userId), gconv.String(v))
+			_, e = enforcer.AddGroupingPolicy(fmt.Sprintf("%s%d", s.CasBinUserPrefix, userId), gconv.String(v))
 			liberr.ErrIsNil(ctx, e)
 		}
 	})
@@ -497,9 +501,9 @@ func (s *userImpl) EditUserRole(ctx context.Context, roleIds []int64, userId int
 		liberr.ErrIsNil(ctx, e)
 
 		//删除用户旧角色信息
-		enforcer.RemoveFilteredGroupingPolicy(0, gconv.String(userId))
+		enforcer.RemoveFilteredGroupingPolicy(0, fmt.Sprintf("%s%d", s.CasBinUserPrefix, userId))
 		for _, v := range roleIds {
-			_, err = enforcer.AddGroupingPolicy(gconv.String(userId), gconv.String(v))
+			_, err = enforcer.AddGroupingPolicy(fmt.Sprintf("%s%d", s.CasBinUserPrefix, userId), gconv.String(v))
 			liberr.ErrIsNil(ctx, err)
 		}
 	})
@@ -611,7 +615,7 @@ func (s *userImpl) Delete(ctx context.Context, ids []int) (err error) {
 			enforcer, e := commonService.CasbinEnforcer(ctx)
 			liberr.ErrIsNil(ctx, e)
 			for _, v := range ids {
-				enforcer.RemoveFilteredGroupingPolicy(0, gconv.String(v))
+				enforcer.RemoveFilteredGroupingPolicy(0, fmt.Sprintf("%s%d", s.CasBinUserPrefix, v))
 			}
 			//删除用户对应的岗位
 			_, err = dao.SysUserPost.Ctx(ctx).TX(tx).Delete(dao.SysUserPost.Columns().UserId+" in (?)", ids)

+ 2 - 1
manifest/config/config.yaml.bak

@@ -47,7 +47,8 @@ gfToken:
   encryptKey: "49c54195e750b04e74a8429b17896586"
   cacheModel: "redis"
   excludePaths:
-    - "/api/v1/system/login"
+    - "/api/v1/system/xxx"
+    - "/api/v1/system/xxx2"
 
 # Redis 配置示例
 redis: