package service import ( "fmt" "time" "be.ems/src/framework/config" "be.ems/src/framework/constants" "be.ems/src/framework/database/redis" "be.ems/src/framework/token" "be.ems/src/framework/utils/crypto" "be.ems/src/framework/utils/parse" systemModelVO "be.ems/src/modules/system/model/vo" systemService "be.ems/src/modules/system/service" ) // 实例化服务层 Account 结构体 var NewAccount = &Account{ sysUserService: systemService.NewSysUser, sysConfigService: systemService.NewSysConfig, sysRoleService: systemService.NewSysRole, sysMenuService: systemService.NewSysMenu, } // 账号身份操作服务 服务层处理 type Account struct { sysUserService *systemService.SysUser // 用户信息服务 sysConfigService *systemService.SysConfig // 参数配置服务 sysRoleService *systemService.SysRole // 角色服务 sysMenuService *systemService.SysMenu // 菜单服务 } // ValidateCaptcha 校验验证码 func (s *Account) ValidateCaptcha(code, uuid string) error { // 验证码检查,从数据库配置获取验证码开关 true开启,false关闭 captchaEnabledStr := s.sysConfigService.FindValueByKey("sys.account.captchaEnabled") if !parse.Boolean(captchaEnabledStr) { return nil } if code == "" || uuid == "" { // 验证码信息错误 return fmt.Errorf("captcha.err") } verifyKey := constants.CACHE_CAPTCHA_CODE + ":" + uuid captcha, _ := redis.Get("", verifyKey) if captcha == "" { // 验证码已失效 return fmt.Errorf("captcha.errValid") } _ = redis.Del("", verifyKey) if captcha != code { // 验证码错误 return fmt.Errorf("captcha.err") } return nil } // ByUsername 登录创建用户信息 func (s Account) ByUsername(username, password string) (token.TokenInfo, error) { tokenInfo := token.TokenInfo{} // 检查密码重试次数 retryKey, retryCount, lockTime, err := s.passwordRetryCount(username) if err != nil { return tokenInfo, err } // 查询用户登录账号 sysUser := s.sysUserService.FindByUserName(username) if sysUser.UserName != username { return tokenInfo, fmt.Errorf("login.errNameOrPasswd") } if sysUser.DelFlag == constants.STATUS_YES { return tokenInfo, fmt.Errorf("login.errDelFlag") } if sysUser.StatusFlag == constants.STATUS_NO { return tokenInfo, fmt.Errorf("login.errStatus") } // 检验用户密码 compareBool := crypto.BcryptCompare(password, sysUser.Password) if compareBool { s.CleanLoginRecordCache(sysUser.UserName) // 清除错误记录次数 } else { _ = redis.SetByExpire("", retryKey, retryCount+1, lockTime) return tokenInfo, fmt.Errorf("login.errNameOrPasswd") } // 登录用户信息 tokenInfo.UserId = sysUser.UserId tokenInfo.DeptId = sysUser.DeptId tokenInfo.User = sysUser // 用户权限组标识 if config.IsSystemUser(sysUser.UserId) { tokenInfo.Permissions = []string{constants.SYS_PERMISSION_SYSTEM} } else { perms := s.sysMenuService.FindPermsByUserId(sysUser.UserId) tokenInfo.Permissions = parse.RemoveDuplicates(perms) } return tokenInfo, nil } // UpdateLoginDateAndIP 更新登录时间和IP func (s Account) UpdateLoginDateAndIP(tokenInfo token.TokenInfo) bool { user := s.sysUserService.FindById(tokenInfo.UserId) user.Password = "" // 密码不更新 user.LoginIp = tokenInfo.LoginIp user.LoginTime = tokenInfo.LoginTime return s.sysUserService.Update(user) > 0 } // CleanLoginRecordCache 清除错误记录次数 func (s Account) CleanLoginRecordCache(userName string) bool { cacheKey := fmt.Sprintf("%s:%s", constants.CACHE_PWD_ERR_COUNT, userName) hasKey, err := redis.Has("", cacheKey) if hasKey > 0 && err == nil { return redis.Del("", cacheKey) == nil } return false } // passwordRetryCount 密码重试次数 func (s Account) passwordRetryCount(userName string) (string, int64, time.Duration, error) { // 从数据库配置获取登录次数和错误锁定时间 maxRetryCountStr := s.sysConfigService.FindValueByKey("sys.user.maxRetryCount") lockTimeStr := s.sysConfigService.FindValueByKey("sys.user.lockTime") // 验证登录次数和错误锁定时间 maxRetryCount := parse.Number(maxRetryCountStr) lockTime := parse.Number(lockTimeStr) // 验证缓存记录次数 retryKey := fmt.Sprintf("%s:%s", constants.CACHE_PWD_ERR_COUNT, userName) retryCount, err := redis.Get("", retryKey) if retryCount == "" || err != nil { retryCount = "0" } // 是否超过错误值 retryCountInt64 := parse.Number(retryCount) if retryCountInt64 >= int64(maxRetryCount) { // msg := fmt.Sprintf("密码输入错误 %d 次,帐户锁定 %d 分钟", maxRetryCount, lockTime) msg := fmt.Errorf("login.errRetryPasswd") // 密码输入错误多次,帐户已被锁定 return retryKey, retryCountInt64, time.Duration(lockTime) * time.Minute, fmt.Errorf("%s", msg) } return retryKey, retryCountInt64, time.Duration(lockTime) * time.Minute, nil } // RoleAndMenuPerms 角色和菜单数据权限 func (s Account) RoleAndMenuPerms(userId int64, isSystemUser bool) ([]string, []string) { if isSystemUser { return []string{constants.SYS_ROLE_SYSTEM_KEY}, []string{constants.SYS_PERMISSION_SYSTEM} } // 角色key var roleGroup []string roles := s.sysRoleService.FindByUserId(userId) for _, role := range roles { roleGroup = append(roleGroup, role.RoleKey) } // 菜单权限key perms := s.sysMenuService.FindPermsByUserId(userId) return parse.RemoveDuplicates(roleGroup), parse.RemoveDuplicates(perms) } // RouteMenus 前端路由所需要的菜单 func (s Account) RouteMenus(userId int64, isSystemUser bool) []systemModelVO.Router { var buildMenus []systemModelVO.Router if isSystemUser { menus := s.sysMenuService.BuildTreeMenusByUserId(0) buildMenus = s.sysMenuService.BuildRouteMenus(menus, "") } else { menus := s.sysMenuService.BuildTreeMenusByUserId(userId) buildMenus = s.sysMenuService.BuildRouteMenus(menus, "") } return buildMenus }