package service import ( "crypto/md5" "encoding/hex" "errors" "fmt" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/entity" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/response" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/client" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/tools" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/resp" "image/color" "strings" "time" "github.com/go-redis/redis" "github.com/mojocn/base64Captcha" uuid "github.com/satori/go.uuid" "github.com/spf13/cast" "go.uber.org/zap" "k8s.io/apimachinery/pkg/util/json" ) type UserSvc struct { SystemAccount string PassWord string } func (u *UserSvc) Login() (msg string, uuidStr string, last_login string, err error) { db, err := client.GetDbClient() if err != nil { return "", "", "", resp.DbConnectError.WithError(err) } // 查询用户 var userInfo entity.SystemUserInfo _, err = db.Table("system_user"). Select("system_user.*"). Where("system_account = ?", u.SystemAccount).Get(&userInfo) if err != nil { return } if userInfo.Id == 0 { conf.Logger.Error("用户名或密码错误", zap.Error(err)) return "", "", "", resp.FAIL.WithMsg("用户名或密码错误") } if userInfo.State == 0 { conf.Logger.Error("账号未启用", zap.Error(err)) return "", "", "", resp.FAIL.WithMsg("账号未启用") } redisCli, err := client.GetRedisClient() if err != nil { return "", "", "", resp.RedisConnectError.WithError(err) } lockKey := fmt.Sprintf("so-operation-user-lock-%v", userInfo.Id) haslock, err := redisCli.Get(lockKey) if err != nil && err != redis.Nil { conf.Logger.Error("获取密码插入次数失败", zap.Error(err)) return "", "", "", resp.DbSelectError.WithError(err) } else if haslock == "" { if err := redisCli.Set(lockKey, 0, conf.LockDuration); err != nil { conf.Logger.Error("密码插入次数插入redis失败", zap.Error(err)) return "", "", "", resp.DbInsertError.WithError(err) } } else if cast.ToInt(haslock) >= conf.LockErrorNumber { if ttl, err := redisCli.Ttl(lockKey); err != nil { msg = "错误次数达到上限,请稍后重试" } else { if ttl.Seconds() <= 0 { if err := redisCli.Del(lockKey); err != nil { msg = "删除错误次数错误,请稍后重试" } ttl = time.Second } ttl := int(ttl.Seconds()) if ttl >= 3600 { msg = fmt.Sprintf("错误次数达到上限,请%d小时后重试", ttl/3600) } else if ttl >= 60 && ttl < 3600 { msg = fmt.Sprintf("错误次数达到上限,请%d分钟后重试", ttl/60) } else { msg = fmt.Sprintf("错误次数达到上限,请%d秒后重试", ttl) } } err = errors.New(msg) if err != nil { conf.Logger.Error(msg, zap.Error(err)) return "", "", "", resp.RedisExecError.WithError(err) } } h := md5.New() _, err = h.Write([]byte(strings.ToUpper(fmt.Sprintf("%d-%s", userInfo.Id, u.PassWord)))) if err != nil { conf.Logger.Error("加密错误", zap.Error(err)) return "", "", "", resp.FAIL.WithError(err) } uppperMd5Pass := strings.ToUpper(hex.EncodeToString(h.Sum(nil))) if uppperMd5Pass != userInfo.Password { incr, err := redisCli.Incr(lockKey) if err != nil { conf.Logger.Error("写入错误次数失败", zap.Error(err)) return "", "", "", resp.RedisExecError.WithError(err) } conf.Logger.Info("当前错误次数为", zap.Int64("incr", incr)) //再次错误执行续期 expire, err := redisCli.Expire(lockKey, conf.LockDuration) if err != nil { conf.Logger.Error("错误次数续期错误", zap.Error(err)) return "", "", "", resp.RedisExecError.WithError(err) } conf.Logger.Info("续期结果为", zap.Bool("expire", expire)) return "", "", "", resp.FAIL.WithMsg("用户名或密码错误") } //密码正确 删除 锁定文件 if err := redisCli.Del(lockKey); err != nil { conf.Logger.Error("删除锁定文件错误", zap.Error(err)) return "", "", "", resp.RedisExecError.WithError(err) } uu := uuid.NewV4() uuidStr = uu.String() // 存入redis b, err := json.Marshal(userInfo) if err != nil { return "", "", "", resp.FAIL.WithError(err) } err = redisCli.Set(uuidStr, string(b), time.Minute*60*24) if err != nil { conf.Logger.Error("登录失败", zap.Error(err)) return "", "", "", resp.FAIL.WithError(err) } msg = "登录成功" conf.Logger.Info("登录成功", zap.String("msg", msg)) //登录时间计录在map loginMap := make(map[string]string, 0) cont, _ := redisCli.Get("LOGIN-TIME") //if err != nil { // conf.Logger.Error("获取登录时间失败", zap.Error(err)) // return "", "", "", res.DataFailError.ErrorDetail(err) //} if cont != "" { err = json.Unmarshal([]byte(cont), &loginMap) if err != nil { return "", "", "", resp.FAIL.WithError(err) } } now := time.Now().Format(conf.LocalDateTimeFormat) if _, ok := loginMap[u.SystemAccount]; ok { last_login = loginMap[u.SystemAccount] } else { last_login = now } loginMap[u.SystemAccount] = now a, err := json.Marshal(loginMap) if err != nil { return "", "", "", resp.FAIL.WithError(err) } err = redisCli.Set("LOGIN-TIME", string(a), -1) if err != nil { conf.Logger.Error("登录失败", zap.Error(err)) return "", "", "", resp.FAIL.WithError(err) } return } func (u *UserSvc) GetCurUser(token string) (m entity.SystemUserInfo, err error) { rcon, err := client.GetRedisClient() if err != nil { return m, resp.RedisConnectError.WithError(err) } result, err := rcon.Get(token) if err != nil { if err.Error() == "redis: nil" { err = errors.New("登录超时") return m, resp.FAIL.WithError(err) } else { conf.Logger.Error("获取token失败", zap.Error(err)) return m, resp.FAIL.WithError(err) } } if result == "" { err = errors.New("登录超时") return m, resp.FAIL.WithError(err) } err = json.Unmarshal([]byte(result), &m) if err != nil { return m, resp.FAIL.WithError(err) } m.Password = "" return } func (u *UserSvc) UserLogout(cookie string) (msg string, err error) { // 清理redis redisCli, err := client.GetRedisClient() if err != nil { return "", resp.FAIL.WithError(err) } err = redisCli.Del(cookie) if err != nil { msg = "登出失败" return msg, resp.FAIL.WithError(err) } return "登出成功", nil } func (u *UserSvc) GetCaptcha(width, height int) (captcha response.Captcha, err error) { param := tools.ConfigJsonBody{ CaptchaType: "string", DriverString: &base64Captcha.DriverString{ Height: height, Width: width, NoiseCount: 0, ShowLineOptions: 2, Length: 4, Source: "124567890", BgColor: &color.RGBA{255, 255, 255, 1}, //Fonts: []string{"3Dumb.ttf", "ApothecaryFont.ttf", "Comismsh.ttf", "DENNEthree-dee.ttf", "DeborahFancyDress.ttf", // "Flim-Flam.ttf", "RitaSmith.ttf", "actionj.ttf", "chromohv.ttf"}, Fonts: []string{"DENNEthree-dee.ttf"}, }, } captcha.Id, captcha.Captcha, err = tools.GenerateCaptcha(param) return } func (u *UserSvc) VerifyCaptcha(id, value string) (err error) { param := tools.ConfigJsonBody{} param.Id = id param.VerifyValue = strings.ToLower(value) right := tools.Verify(param) if !right { err = errors.New("验证码不正确") conf.Logger.Error("验证码不正确", zap.Error(err)) } return }