package auth import ( "context" "errors" "github.com/goccy/go-json" "gofiber.study.skcks.cn/common/logger" "gofiber.study.skcks.cn/common/utils" "gofiber.study.skcks.cn/global" "gofiber.study.skcks.cn/model/dto" "gofiber.study.skcks.cn/model/generic/models" "gofiber.study.skcks.cn/model/vo" "time" ) var ( PasswordIsEmpty = errors.New("密码不能为空") Failed = errors.New("账号或密码错误") InvalidRefreshToken = errors.New("刷新令牌已失效") ) const ( Separator = ":" RefreshTokenPrefix = "RefreshToken" + Separator ) type Service struct { } var Services *Service func InitService() { Services = &Service{} } // generateAndSaveRefreshToken // // 生成并保存 refreshToken 刷新令牌 func (s *Service) generateAndSaveRefreshToken(user *models.User) (refreshToken string, err error) { refreshToken, err = global.GetNanoId() if err != nil { return } expire := time.Duration(global.Config.Jwt.Expire*2) * time.Second ctx := context.Background() global.Redis.Set(ctx, RefreshTokenPrefix+refreshToken, utils.Json(user), expire) return } func (s *Service) Login(login *dto.Login) (result *vo.Login, err error) { err = global.ValidateStruct(login) if err != nil { return nil, err } user := &models.User{Account: login.Account, Password: login.Password} exist, err := global.DataSources.Get(user) if err != nil { return } if !exist { return nil, Failed } token, err := global.GetToken(global.UserClaims{ Id: user.Id, Account: user.Account, }) if err != nil { return } refreshToken, err := s.generateAndSaveRefreshToken(user) _, _ = global.DataSources.Update(user) return &vo.Login{ Token: token, RefreshToken: refreshToken, }, err } func (s *Service) RefreshToken(refreshToken string) (result *vo.Login, err error) { refreshToken = RefreshTokenPrefix + refreshToken ctx := context.Background() data, err := global.Redis.Get(ctx, refreshToken).Result() if err != nil { return nil, InvalidRefreshToken } global.Redis.Del(ctx, refreshToken) cache := &models.User{} err = json.Unmarshal([]byte(data), cache) if err != nil { return nil, InvalidRefreshToken } user := &models.User{Id: cache.Id, Account: cache.Account} exist, err := global.DataSources.Get(user) if !exist { logger.Log.Infof("未能从 %s 找到用户信息", refreshToken) return nil, InvalidRefreshToken } token, err := global.GetToken(global.UserClaims{ Id: user.Id, Account: user.Account, }) if err != nil { return } refreshToken, err = s.generateAndSaveRefreshToken(user) return &vo.Login{ Token: token, RefreshToken: refreshToken, }, err }