Merge pull request 'feat-IRONFANS-248-Robin' (#845) from feat-IRONFANS-248-Robin into main
Reviewed-on: http://121.41.31.146:3000/wishpal_ironfan/service/pulls/845
This commit is contained in:
commit
2f168599ee
|
@ -36,6 +36,7 @@ const (
|
|||
// apollo_config
|
||||
const (
|
||||
MaxPswdWrongTimesKey = "max_pswd_wrong_times"
|
||||
MaxVeriCodeWrongTimesKey = "max_veri_code_wrong_times"
|
||||
MaxVeriCodeValidDurationKey = "max_veri_code_valid_duration"
|
||||
IosKey = "ios"
|
||||
AndroidKey = "android"
|
||||
|
|
|
@ -251,6 +251,10 @@ var ErrCodeMsgMap = map[ErrCode]string{
|
|||
ErrCodeEmailSrvFail: "电子邮件表服务错误",
|
||||
ErrCodeEmailNotExist: "电子邮件表不存在",
|
||||
|
||||
ErrCodeVeriCodeWrongTimesSrvFail: "验证码错误频次表服务错误",
|
||||
ErrCodeVeriCodeWrongTimesNotExist: "验证码错误频次表不存在",
|
||||
ErrCodeVeriCodeWrongTimesReachedDailyUpperbound: "账户已锁定,请明日再试",
|
||||
|
||||
ErrCodeRavenIQTestSrvFail: "瑞文智商测试表服务错误",
|
||||
ErrCodeRavenIQTestNotExist: "瑞文智商测试表不存在",
|
||||
ErrCodeRavenIQTestQuestionNotExist: "瑞文智商测试表题目不存在",
|
||||
|
@ -599,6 +603,12 @@ const (
|
|||
ErrCodeEmailSrvFail ErrCode = -45001 // 电子邮件表服务错误
|
||||
ErrCodeEmailNotExist ErrCode = -45002 // 电子邮件表不存在
|
||||
|
||||
// MomentCreateTimes: 49xxx
|
||||
ErrCodeVeriCodeWrongTimesSrvOk ErrCode = ErrCodeOk
|
||||
ErrCodeVeriCodeWrongTimesSrvFail ErrCode = -49001 // 验证码错误频次表服务错误
|
||||
ErrCodeVeriCodeWrongTimesNotExist ErrCode = -49002 // 验证码错误频次表不存在
|
||||
ErrCodeVeriCodeWrongTimesReachedDailyUpperbound ErrCode = -49003 // 验证码错误次数已达每日上限
|
||||
|
||||
// Media: 60xxx
|
||||
ErrCodeMediaSrvOk ErrCode = ErrCodeOk
|
||||
ErrCodeMediaSrvFail ErrCode = -60001 // 媒体服务错误
|
||||
|
|
|
@ -111,6 +111,7 @@ const (
|
|||
DBLogin = "login"
|
||||
COLLogin = "login"
|
||||
COLLoginHis = "login_his"
|
||||
COLVeriCodeWrongTimes = "veri_code_wrong_times"
|
||||
|
||||
DBToken = "token"
|
||||
COLToken = "token"
|
||||
|
@ -337,6 +338,11 @@ func (m *Mongo) getColLoginHis() *qmgo.Collection {
|
|||
return m.clientMix.Database(DBLogin).Collection(COLLoginHis)
|
||||
}
|
||||
|
||||
// 验证码错误频次表
|
||||
func (m *Mongo) getColVeriCodeWrongTimes() *qmgo.Collection {
|
||||
return m.clientMix.Database(DBLogin).Collection(COLLoginHis)
|
||||
}
|
||||
|
||||
// Token表
|
||||
func (m *Mongo) getColToken() *qmgo.Collection {
|
||||
return m.clientMix.Database(DBToken).Collection(COLToken)
|
||||
|
@ -6432,3 +6438,54 @@ func (m *Mongo) GetRavenIQTestVisitUV(ctx *gin.Context, req *Raven_IQ_test_visit
|
|||
|
||||
return
|
||||
}
|
||||
|
||||
// 验证码错误频次
|
||||
func (m *Mongo) GetAndUpdateVeriCodeWrongTimes(ctx *gin.Context, mid int64) (veriCodeWrongTimes *dbstruct.VeriCodeWrongTimes, err error) {
|
||||
col := m.getColVeriCodeWrongTimes()
|
||||
|
||||
change := qmgo.Change{
|
||||
Update: qmgo.M{"$inc": qmgo.M{"wrong_times": 1}},
|
||||
Upsert: true,
|
||||
ReturnNew: false,
|
||||
}
|
||||
|
||||
veriCodeWrongTimesInstance := dbstruct.VeriCodeWrongTimes{}
|
||||
if err = col.Find(ctx, qmgo.M{"_id": mid}).Apply(change, &veriCodeWrongTimesInstance); err != nil {
|
||||
logger.Error("change error : %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
return &veriCodeWrongTimesInstance, err
|
||||
}
|
||||
|
||||
// 验证码错误频次
|
||||
func (m *Mongo) GetVeriCodeWrongTimes(ctx *gin.Context, id int64) (*dbstruct.VeriCodeWrongTimes, error) {
|
||||
veriCodeWrongTimes := &dbstruct.VeriCodeWrongTimes{}
|
||||
|
||||
col := m.getColVeriCodeWrongTimes()
|
||||
query := qmgo.M{
|
||||
"_id": id,
|
||||
}
|
||||
|
||||
err := col.Find(ctx, query).One(veriCodeWrongTimes)
|
||||
if err == qmgo.ErrNoSuchDocuments {
|
||||
err = nil
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return veriCodeWrongTimes, err
|
||||
}
|
||||
|
||||
// 删除验证码错误频次表
|
||||
func (m *Mongo) DeleteVeriCodeWrongTimes(ctx *gin.Context, id int64) error {
|
||||
col := m.getColVeriCodeWrongTimes()
|
||||
err := col.RemoveId(ctx, id)
|
||||
return err
|
||||
}
|
||||
|
||||
// 清空验证码错误频次表
|
||||
func (m *Mongo) ClearVeriCodeWrongTimes(ctx *gin.Context) error {
|
||||
col := m.getColVeriCodeWrongTimes()
|
||||
_, err := col.RemoveAll(ctx, qmgo.M{})
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -97,11 +97,12 @@ func (s *Service) ApiLoginByVeriCodeBusinessValidate(ctx *gin.Context, req *logi
|
|||
// 1.业务校验
|
||||
req.CalcPhoneHash() //计算手机号哈希
|
||||
resultList := businessvalidator.NewLoginBusinessValidator(ctx, req).
|
||||
QueryLogin(_DefaultLogin.OpListByPhoneHash).
|
||||
EnsureVeriCodeWrongTimesNotReachedDailyUpperbound(_DefaultVeriCodeWrongTimes.OpGet).
|
||||
QueryVeriCode(_DefaultVeriCode.OpListByPhoneHash).
|
||||
EnsureVeriCodeExist().
|
||||
EnsureVeriCodeIsCorrect().
|
||||
EnsureVeriCodeIsCorrect(_DefaultVeriCodeWrongTimes.OpGetAndUpdate).
|
||||
EnsureVeriCodeIsValid().
|
||||
QueryLogin(_DefaultLogin.OpListByPhoneHash).
|
||||
EnsureLoginExist().
|
||||
//EnsureLoginAcctNotLocked(). //验证码登录不校验是否爆破登录
|
||||
EnsureLoginAcctNotBanned().
|
||||
|
@ -161,12 +162,13 @@ func (s *Service) ApiResetPasswordBusinessValidate(ctx *gin.Context, req *loginp
|
|||
// 1.业务校验
|
||||
req.CalcPhoneHash() //计算手机号哈希
|
||||
resultList := businessvalidator.NewLoginBusinessValidator(ctx, req).
|
||||
QueryVeriCode(_DefaultVeriCode.OpListByPhoneHash).
|
||||
EnsureVeriCodeExist().
|
||||
EnsureVeriCodeIsCorrect().
|
||||
EnsureVeriCodeIsValid().
|
||||
QueryLogin(_DefaultLogin.OpListByPhoneHash).
|
||||
EnsureLoginExist().
|
||||
EnsureVeriCodeWrongTimesNotReachedDailyUpperbound(_DefaultVeriCodeWrongTimes.OpGet).
|
||||
QueryVeriCode(_DefaultVeriCode.OpListByPhoneHash).
|
||||
EnsureVeriCodeExist().
|
||||
EnsureVeriCodeIsCorrect(_DefaultVeriCodeWrongTimes.OpGetAndUpdate).
|
||||
EnsureVeriCodeIsValid().
|
||||
EnsureLoginAcctEnabled().
|
||||
EnsureLoginAcctNotBanned().
|
||||
EnsureNewPasswordIsChanged().
|
||||
|
@ -195,12 +197,13 @@ func (s *Service) ApiUpdatePasswordBusinessValidate(ctx *gin.Context, req *login
|
|||
// 1.业务校验
|
||||
req.CalcPhoneHash() //计算手机号哈希
|
||||
resultList := businessvalidator.NewLoginBusinessValidator(ctx, req).
|
||||
QueryVeriCode(_DefaultVeriCode.OpListByPhoneHash).
|
||||
EnsureVeriCodeExist().
|
||||
EnsureVeriCodeIsCorrect().
|
||||
EnsureVeriCodeIsValid().
|
||||
QueryLogin(_DefaultLogin.OpListByPhoneHash).
|
||||
EnsureLoginExist().
|
||||
EnsureVeriCodeWrongTimesNotReachedDailyUpperbound(_DefaultVeriCodeWrongTimes.OpGet).
|
||||
QueryVeriCode(_DefaultVeriCode.OpListByPhoneHash).
|
||||
EnsureVeriCodeExist().
|
||||
EnsureVeriCodeIsCorrect(_DefaultVeriCodeWrongTimes.OpGetAndUpdate).
|
||||
EnsureVeriCodeIsValid().
|
||||
EnsureLoginAcctEnabled().
|
||||
EnsureLoginAcctNotLocked().
|
||||
EnsureLoginAcctNotBanned().
|
||||
|
@ -701,7 +704,7 @@ func (s *Service) ApiCreateZoneThirdPartnerBusinessValidate(ctx *gin.Context, re
|
|||
resultList := businessvalidator.NewLoginBusinessValidator(ctx, req).
|
||||
QueryVeriCode(_DefaultVeriCode.OpListByPhoneHash).
|
||||
EnsureVeriCodeExist().
|
||||
EnsureVeriCodeIsCorrect().
|
||||
EnsureVeriCodeIsCorrect(_DefaultVeriCodeWrongTimes.OpGetAndUpdate).
|
||||
EnsureVeriCodeIsValid().
|
||||
Validate().
|
||||
Collect()
|
||||
|
|
|
@ -107,6 +107,39 @@ func (l *LoginBusinessValidator) EnsureLoginAcctNotBanned() *LoginBusinessValida
|
|||
return l
|
||||
}
|
||||
|
||||
func (l *LoginBusinessValidator) EnsureVeriCodeWrongTimesNotReachedDailyUpperbound(fun func(*gin.Context, int64) (*dbstruct.VeriCodeWrongTimes, error)) *LoginBusinessValidator {
|
||||
l.oplist = append(l.oplist, func() {
|
||||
|
||||
if l.login != nil {
|
||||
|
||||
wrongTimes, err := fun(l.ctx, l.login.GetMid())
|
||||
if err != nil {
|
||||
l.ec = errcode.ErrCodeVeriCodeWrongTimesSrvFail
|
||||
return
|
||||
}
|
||||
if wrongTimes == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 读取每日错误上限
|
||||
maxDailyWrongTimes, err := apollo.GetIntValue(consts.MaxVeriCodeWrongTimesKey, apollo.ApolloOpts().SetNamespace("application"))
|
||||
if err != nil {
|
||||
logger.Error("Apollo read failed : %v", err)
|
||||
l.ec = errcode.ErrCodeApolloReadFail
|
||||
return
|
||||
}
|
||||
|
||||
if wrongTimes.WrongTimes >= int64(maxDailyWrongTimes) {
|
||||
logger.Error("wrongs times of verification code of this mid has reached its daily upperbound")
|
||||
l.ec = errcode.ErrCodeVeriCodeWrongTimesReachedDailyUpperbound
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
return l
|
||||
}
|
||||
|
||||
func (l *LoginBusinessValidator) EnsurePasswordIsCorrect() *LoginBusinessValidator {
|
||||
l.oplist = append(l.oplist, func() {
|
||||
if l.passwordAccessor.GetPassword() != util.DerefString(l.login.Password) {
|
||||
|
@ -194,10 +227,19 @@ func (l *LoginBusinessValidator) EnsureVeriCodeExist() *LoginBusinessValidator {
|
|||
return l
|
||||
}
|
||||
|
||||
func (l *LoginBusinessValidator) EnsureVeriCodeIsCorrect() *LoginBusinessValidator {
|
||||
func (l *LoginBusinessValidator) EnsureVeriCodeIsCorrect(fun func(*gin.Context, int64) (*dbstruct.VeriCodeWrongTimes, error)) *LoginBusinessValidator {
|
||||
l.oplist = append(l.oplist, func() {
|
||||
if l.vericode.VeriCode != l.vericodeAccessor.GetVeriCode() {
|
||||
logger.Error("Wrong verification code")
|
||||
|
||||
// 如果不是首次登录,则错误次数+1
|
||||
if l.login != nil {
|
||||
_, err := fun(l.ctx, l.login.GetMid())
|
||||
if err != nil {
|
||||
logger.Error("GetAndUpdateVeriCodeWrongTimes failed, err :%v", err)
|
||||
}
|
||||
}
|
||||
|
||||
l.ec = errcode.ErrCodeLoginWrongVeriCode
|
||||
return
|
||||
}
|
||||
|
|
|
@ -86,6 +86,7 @@ func (s *CronService) Init(c any) (exec xxl.Executor, err error) {
|
|||
exec.RegTask("clear_expired_btcb", s.ClearExpiredBtcb)
|
||||
exec.RegTask("reload_blocked_from_being_searched_list", s.ReloadBlockedFromBeingSearchedList)
|
||||
exec.RegTask("clear_auto_response_create_times", s.ClearAutoResponseCreateTimes)
|
||||
exec.RegTask("clear_veri_code_wrong_times", s.ClearVeriCodeWrongTimes)
|
||||
exec.LogHandler(customLogHandle)
|
||||
//注册任务handler
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package logic
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"service/api/base"
|
||||
tokenproto "service/api/proto/token/proto"
|
||||
"service/app/mix/dao"
|
||||
"service/dbstruct"
|
||||
|
@ -168,5 +169,11 @@ func (p *Token) OpVerifyValid(ctx *gin.Context, token *jwt.Token) (int64, error)
|
|||
return -1, fmt.Errorf("登录失效,请重新登录!")
|
||||
}
|
||||
|
||||
// 校验是否本人
|
||||
req := ctx.MustGet("client_req").(base.BaseRequestAccessible)
|
||||
if list[0].Mid != req.GetBaseRequest().Mid {
|
||||
return -1, fmt.Errorf("非法令牌!")
|
||||
}
|
||||
|
||||
return tokenUuid, nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
package logic
|
||||
|
||||
import (
|
||||
"service/app/mix/dao"
|
||||
"service/dbstruct"
|
||||
"service/library/logger"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type VeriCodeWrongTimes struct {
|
||||
store *dao.Store
|
||||
}
|
||||
|
||||
func NewVeriCodeWrongTimes(store *dao.Store) (a *VeriCodeWrongTimes) {
|
||||
a = &VeriCodeWrongTimes{
|
||||
store: store,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (p *VeriCodeWrongTimes) OpGet(ctx *gin.Context, mid int64) (*dbstruct.VeriCodeWrongTimes, error) {
|
||||
|
||||
veriCodeWrongTimes, err := p.store.GetVeriCodeWrongTimes(ctx, mid)
|
||||
if err != nil {
|
||||
logger.Error("GetVeriCodeWrongTimes fail, err: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return veriCodeWrongTimes, nil
|
||||
}
|
||||
|
||||
func (p *VeriCodeWrongTimes) OpGetAndUpdate(ctx *gin.Context, mid int64) (*dbstruct.VeriCodeWrongTimes, error) {
|
||||
|
||||
veriCodeWrongTimes, err := p.store.GetAndUpdateVeriCodeWrongTimes(ctx, mid)
|
||||
if err != nil {
|
||||
logger.Error("GetAndUpdateVeriCodeWrongTimes fail, err: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return veriCodeWrongTimes, nil
|
||||
}
|
||||
|
||||
func (p *VeriCodeWrongTimes) OpDelete(ctx *gin.Context, mid int64) error {
|
||||
err := p.store.DeleteVeriCodeWrongTimes(ctx, mid)
|
||||
if err != nil {
|
||||
logger.Error("DeleteVeriCodeWrongTimes fail, err: %v", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *VeriCodeWrongTimes) OpClear(ctx *gin.Context) error {
|
||||
err := p.store.ClearVeriCodeWrongTimes(ctx)
|
||||
if err != nil {
|
||||
logger.Error("ClearVeriCodeWrongTimes fail, err: %v", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -106,11 +106,12 @@ func (s *Service) OpLoginByVeriCodeBusinessValidate(ctx *gin.Context, req *login
|
|||
// 1.业务校验
|
||||
req.CalcPhoneHash() //计算手机号哈希
|
||||
resultList := businessvalidator.NewLoginBusinessValidator(ctx, req).
|
||||
QueryLogin(_DefaultLogin.OpListByPhoneHash).
|
||||
EnsureVeriCodeWrongTimesNotReachedDailyUpperbound(_DefaultVeriCodeWrongTimes.OpGet).
|
||||
QueryVeriCode(_DefaultVeriCode.OpListByPhoneHash).
|
||||
EnsureVeriCodeExist().
|
||||
EnsureVeriCodeIsCorrect().
|
||||
EnsureVeriCodeIsCorrect(_DefaultVeriCodeWrongTimes.OpGetAndUpdate).
|
||||
EnsureVeriCodeIsValid().
|
||||
QueryLogin(_DefaultLogin.OpListByPhoneHash).
|
||||
EnsureLoginExist().
|
||||
EnsureLoginAcctNotLocked().
|
||||
EnsureLoginAcctNotBanned().
|
||||
|
@ -172,12 +173,13 @@ func (s *Service) OpResetPasswordBusinessValidate(ctx *gin.Context, req *loginpr
|
|||
// 1.业务校验
|
||||
req.CalcPhoneHash() //计算手机号哈希
|
||||
resultList := businessvalidator.NewLoginBusinessValidator(ctx, req).
|
||||
QueryVeriCode(_DefaultVeriCode.OpListByPhoneHash).
|
||||
EnsureVeriCodeExist().
|
||||
EnsureVeriCodeIsCorrect().
|
||||
EnsureVeriCodeIsValid().
|
||||
QueryLogin(_DefaultLogin.OpListByPhoneHash).
|
||||
EnsureLoginExist().
|
||||
EnsureVeriCodeWrongTimesNotReachedDailyUpperbound(_DefaultVeriCodeWrongTimes.OpGet).
|
||||
QueryVeriCode(_DefaultVeriCode.OpListByPhoneHash).
|
||||
EnsureVeriCodeExist().
|
||||
EnsureVeriCodeIsCorrect(_DefaultVeriCodeWrongTimes.OpGetAndUpdate).
|
||||
EnsureVeriCodeIsValid().
|
||||
EnsureLoginAcctEnabled().
|
||||
EnsureLoginAcctNotBanned().
|
||||
EnsureNewPasswordIsChanged().
|
||||
|
@ -207,12 +209,13 @@ func (s *Service) OpUpdatePasswordBusinessValidate(ctx *gin.Context, req *loginp
|
|||
// 1.业务校验
|
||||
req.CalcPhoneHash() //计算手机号哈希
|
||||
resultList := businessvalidator.NewLoginBusinessValidator(ctx, req).
|
||||
QueryVeriCode(_DefaultVeriCode.OpListByPhoneHash).
|
||||
EnsureVeriCodeExist().
|
||||
EnsureVeriCodeIsCorrect().
|
||||
EnsureVeriCodeIsValid().
|
||||
QueryLogin(_DefaultLogin.OpListByPhoneHash).
|
||||
EnsureLoginExist().
|
||||
EnsureVeriCodeWrongTimesNotReachedDailyUpperbound(_DefaultVeriCodeWrongTimes.OpGet).
|
||||
QueryVeriCode(_DefaultVeriCode.OpListByPhoneHash).
|
||||
EnsureVeriCodeExist().
|
||||
EnsureVeriCodeIsCorrect(_DefaultVeriCodeWrongTimes.OpGetAndUpdate).
|
||||
EnsureVeriCodeIsValid().
|
||||
EnsureLoginAcctEnabled().
|
||||
EnsureLoginAcctNotLocked().
|
||||
EnsureLoginAcctNotBanned().
|
||||
|
|
|
@ -154,6 +154,7 @@ var (
|
|||
_DefaultEmail *logic.Email
|
||||
_DefaultRavenIQTest *logic.RavenIQTest
|
||||
_DefaultRavenIQTestVisit *logic.RavenIQTestVisit
|
||||
_DefaultVeriCodeWrongTimes *logic.VeriCodeWrongTimes
|
||||
|
||||
_DefaultStreamerDecrtByEs *logic.StreamerDecrtByEs
|
||||
_DefaultZoneDecrtByEs *logic.ZoneDecrtByEs
|
||||
|
@ -260,6 +261,7 @@ func (s *Service) Init(c any) (err error) {
|
|||
_DefaultEmail = logic.NewEmail(store)
|
||||
_DefaultRavenIQTest = logic.NewRavenIQTest(store)
|
||||
_DefaultRavenIQTestVisit = logic.NewRavenIQTestVisit(store)
|
||||
_DefaultVeriCodeWrongTimes = logic.NewVeriCodeWrongTimes(store)
|
||||
|
||||
_DefaultVas = logic.NewVas(store, _DefaultStreamer, _DefaultAccount, _DefaultZone, _DefaultZoneThirdPartner, _DefaultZoneCollaborator)
|
||||
_DefaultStreamerAcct = logic.NewStreamerAcct(store)
|
||||
|
|
|
@ -607,3 +607,14 @@ func (s *CronService) ClearAutoResponseCreateTimes(ctx context.Context, param *x
|
|||
logger.Info("auto_response_create_times collection has been cleared")
|
||||
return "auto_response_create_times collection has been cleared"
|
||||
}
|
||||
|
||||
func (s *CronService) ClearVeriCodeWrongTimes(ctx context.Context, param *xxl.RunReq) (msg string) {
|
||||
logger.Info("task %v param: %v log_id: %v", param.ExecutorHandler, param.ExecutorParams, xxl.Int64ToStr(param.LogID))
|
||||
logger.Info("Clearing vericode_wrong_times collection...")
|
||||
if err := _DefaultVeriCodeWrongTimes.OpClear(&gin.Context{}); err != nil {
|
||||
logger.Error("Clear vericode_wrong_times collection fail: %v", err)
|
||||
return fmt.Sprintf("Clear vericode_wrong_times collection fail: %v", err)
|
||||
}
|
||||
logger.Info("vericode_wrong_times collection has been cleared")
|
||||
return "vericode_wrong_times collection has been cleared"
|
||||
}
|
||||
|
|
|
@ -16,3 +16,10 @@ type Login struct {
|
|||
Ut *int64 `json:"ut" bson:"ut"` // 更新时间
|
||||
DelFlag *int64 `json:"del_flag" bson:"del_flag"` // 删除标记,0-否,1-是
|
||||
}
|
||||
|
||||
func (p *Login) GetMid() int64 {
|
||||
if p == nil || p.Mid == nil {
|
||||
return -1
|
||||
}
|
||||
return *p.Mid
|
||||
}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
package dbstruct
|
||||
|
||||
type VeriCodeWrongTimes struct {
|
||||
Id int64 `json:"id" bson:"_id"` //id,用户的mid
|
||||
WrongTimes int64 `json:"wrong_times" bson:"wrong_times"` //错误次数
|
||||
}
|
Loading…
Reference in New Issue