diff --git a/api/errcode/errcode.go b/api/errcode/errcode.go index dba61f50..e4d8788c 100644 --- a/api/errcode/errcode.go +++ b/api/errcode/errcode.go @@ -29,18 +29,19 @@ var ErrCodeMsgMap = map[ErrCode]string{ ErrCodeResourceSrvFail: "资源位服务错误", ErrCodeResourceNotExist: "资源位不存在", - ErrCodeLoginSrvFail: "登录服务错误", - ErrCodeLoginNotExist: "登录信息不存在", - ErrCodeLoginWrongPswd: "登录密码错误", - ErrCodeLoginWrongVeriCode: "验证码错误", - ErrCodeLoginVeriCodeExpired: "验证码已过期", - ErrCodeLoginAcctLocked: "账户已锁定,请明日再试", - ErrCodeLoginAcctBanned: "登录账户已被封禁", - ErrCodeLoginAcctNotEnabled: "登录账户未设置密码,请使用验证码登录", - ErrCodeLoginNoChangeInAPswdReset: "新旧密码相同", - ErrCodeLoginRegisterUserFail: "账号注册失败,请稍后重试", - ErrCodeLoginWrongOldPswd: "旧密码错误", - ErrCodeLoginVeriCodeSendFail: "验证码发送失败:%s", + ErrCodeLoginSrvFail: "登录服务错误", + ErrCodeLoginNotExist: "登录信息不存在", + ErrCodeLoginWrongPswd: "登录密码错误", + ErrCodeLoginWrongVeriCode: "验证码错误", + ErrCodeLoginVeriCodeExpired: "验证码已过期", + ErrCodeLoginAcctLocked: "账户已锁定,请明日再试", + ErrCodeLoginAcctBanned: "登录账户已被封禁", + ErrCodeLoginAcctNotEnabled: "登录账户未设置密码,请使用验证码登录", + ErrCodeLoginNoChangeInAPswdReset: "新旧密码相同", + ErrCodeLoginRegisterUserFail: "账号注册失败,请稍后重试", + ErrCodeLoginWrongOldPswd: "旧密码错误", + ErrCodeLoginVeriCodeSendFail: "验证码发送失败:%s", + ErrCodeLoginMobilePhoneHasBeenRegistered: "该手机号已被注册", ErrCodeAccountSrvFail: "账户服务错误", ErrCodeAccountNotExist: "账户信息不存在", @@ -331,19 +332,20 @@ const ( ErrCodeBannerNotExist ErrCode = -4002 // banner不存在 // Login: 5xxx - ErrCodeLoginSrvOk ErrCode = ErrCodeOk - ErrCodeLoginSrvFail ErrCode = -5001 //登录服务错误 - ErrCodeLoginNotExist ErrCode = -5002 //登录信息不存在 - ErrCodeLoginWrongPswd ErrCode = -5003 //登录密码错误 - ErrCodeLoginWrongVeriCode ErrCode = -5004 //验证码错误 - ErrCodeLoginVeriCodeExpired ErrCode = -5005 //验证码已过期 - ErrCodeLoginAcctLocked ErrCode = -5006 //登录账户尝试爆破登录,已被锁定 - ErrCodeLoginAcctBanned ErrCode = -5007 //登录账户已被封禁 - ErrCodeLoginAcctNotEnabled ErrCode = -5008 //登录账户未启用 - ErrCodeLoginNoChangeInAPswdReset ErrCode = -5009 //新旧密码相同 - ErrCodeLoginRegisterUserFail ErrCode = -5010 //注册账户失败 - ErrCodeLoginWrongOldPswd ErrCode = -5011 //旧密码错误 - ErrCodeLoginVeriCodeSendFail ErrCode = -5012 //验证码发送失败 + ErrCodeLoginSrvOk ErrCode = ErrCodeOk + ErrCodeLoginSrvFail ErrCode = -5001 //登录服务错误 + ErrCodeLoginNotExist ErrCode = -5002 //登录信息不存在 + ErrCodeLoginWrongPswd ErrCode = -5003 //登录密码错误 + ErrCodeLoginWrongVeriCode ErrCode = -5004 //验证码错误 + ErrCodeLoginVeriCodeExpired ErrCode = -5005 //验证码已过期 + ErrCodeLoginAcctLocked ErrCode = -5006 //登录账户尝试爆破登录,已被锁定 + ErrCodeLoginAcctBanned ErrCode = -5007 //登录账户已被封禁 + ErrCodeLoginAcctNotEnabled ErrCode = -5008 //登录账户未启用 + ErrCodeLoginNoChangeInAPswdReset ErrCode = -5009 //新旧密码相同 + ErrCodeLoginRegisterUserFail ErrCode = -5010 //注册账户失败 + ErrCodeLoginWrongOldPswd ErrCode = -5011 //旧密码错误 + ErrCodeLoginVeriCodeSendFail ErrCode = -5012 //验证码发送失败 + ErrCodeLoginMobilePhoneHasBeenRegistered ErrCode = -5012 //手机号已被注册 // Account: 6xxx ErrCodeAccountSrvOk ErrCode = ErrCodeOk diff --git a/api/proto/login/proto/login_op.go b/api/proto/login/proto/login_op.go index 389b41ec..86cfe37c 100644 --- a/api/proto/login/proto/login_op.go +++ b/api/proto/login/proto/login_op.go @@ -182,3 +182,17 @@ type OpUpdateByMidResp struct { base.BaseResponse Data *OpUpdateByMidData `json:"data"` } + +// 更改手机号 +type OpResetMobilePhoneReq struct { + base.BaseRequest + MobilePhoneInfoComponent `jcrypto:"true"` + NewMobilePhone string `json:"new_mobile_phone" jcrypto:"rsa"` // 用户手机号 +} + +type OpResetMobilePhoneData struct{} + +type OpResetMobilePhoneResp struct { + base.BaseResponse + Data *OpResetPswdData `json:"data"` +} diff --git a/app/mix/controller/init.go b/app/mix/controller/init.go index 896a452d..63fb454c 100644 --- a/app/mix/controller/init.go +++ b/app/mix/controller/init.go @@ -429,6 +429,7 @@ func Init(r *gin.Engine) { opLoginGroup.POST("reset_password", middleware.JSONParamValidator(loginproto.OpResetPswdReq{}), middleware.RequestDecryptor(), OpResetPassword) opLoginGroup.POST("update_password", middleware.JSONParamValidator(loginproto.OpUpdatePswdReq{}), middleware.JwtAuthenticator(), middleware.RequestDecryptor(), OpUpdatePassword) opLoginGroup.POST("validate", middleware.JSONParamValidator(base.BaseRequest{}), middleware.JwtAuthenticator(), OpValidate) + opLoginGroup.POST("reset_mobile_phone", middleware.JSONParamValidator(loginproto.OpResetMobilePhoneReq{}), middleware.JwtAuthenticator(), middleware.RequestDecryptor(), OpResetMobilePhone) // 账号 opAccountGroup := r.Group("/op/account", PrepareOp()) diff --git a/app/mix/controller/login_op.go b/app/mix/controller/login_op.go index 040a573d..10f8434e 100644 --- a/app/mix/controller/login_op.go +++ b/app/mix/controller/login_op.go @@ -109,3 +109,15 @@ func OpLogout(ctx *gin.Context) { func OpValidate(ctx *gin.Context) { ReplyOk(ctx, nil) } + +func OpResetMobilePhone(ctx *gin.Context) { + req := ctx.MustGet("client_req").(*loginproto.OpResetMobilePhoneReq) + ec := service.DefaultService.OpResetMobilePhone(ctx, req) + if ec != errcode.ErrCodeLoginSrvOk { + logger.Error("OpResetMobilePhone fail, req: %v, ec: %v", util.ToJson(req), ec) + ReplyErrCodeMsg(ctx, ec) + return + } + + ReplyOk(ctx, nil) +} diff --git a/app/mix/service/business_validator/login.go b/app/mix/service/business_validator/login.go index 60949d06..4c93e593 100644 --- a/app/mix/service/business_validator/login.go +++ b/app/mix/service/business_validator/login.go @@ -10,6 +10,7 @@ import ( "service/dbstruct" "service/library/apollo" "service/library/logger" + "service/library/mycrypto" "time" "github.com/gin-gonic/gin" @@ -77,6 +78,27 @@ func (l *LoginBusinessValidator) EnsureLoginExist() *LoginBusinessValidator { return l } +func (l *LoginBusinessValidator) EnsureNewMobilePhoneNotRegistered(QueryFunc func(ctx *gin.Context, phonehash string) ([]*dbstruct.Account, error), mobilePhone string) *LoginBusinessValidator { + l.oplist = append(l.oplist, func() { + + phoneHash := mycrypto.CryptoServiceInstance().SHA256.Encrypt([]byte(mobilePhone)) + + account, err := QueryFunc(l.ctx, phoneHash) + if err != nil { + logger.Error("Query account failed, err: %v", err) + l.ec = errcode.ErrCodeAccountSrvFail + return + } + if account != nil { + logger.Error("This mobile phone has been registered") + l.ec = errcode.ErrCodeLoginMobilePhoneHasBeenRegistered + return + } + + }) + return l +} + func (l *LoginBusinessValidator) EnsureLoginAcctEnabled() *LoginBusinessValidator { l.oplist = append(l.oplist, func() { if util.DerefInt64(l.login.IsEnabled) == 0 { //账户未启用 diff --git a/app/mix/service/opservice_business_validation.go b/app/mix/service/opservice_business_validation.go index 26360a4b..a03c2767 100644 --- a/app/mix/service/opservice_business_validation.go +++ b/app/mix/service/opservice_business_validation.go @@ -241,6 +241,30 @@ func (s *Service) OpUpdatePasswordBusinessValidate(ctx *gin.Context, req *loginp return } +// 重置手机号 +func (s *Service) OpResetMobilePhoneBusinessValidate(ctx *gin.Context, req *loginproto.OpResetMobilePhoneReq) (login *dbstruct.Login, ec errcode.ErrCode) { + ec = errcode.ErrCodeLoginSrvOk + + // 1.业务校验 + req.CalcPhoneHash() //计算手机号哈希 + resultList := businessvalidator.NewLoginBusinessValidator(ctx, req). + QueryLogin(_DefaultLogin.OpListByPhoneHash). + EnsureLoginExist(). + EnsureNewMobilePhoneNotRegistered(_DefaultAccount.OpListByPhoneHash, req.NewMobilePhone). + Validate(). + Collect() + + // 2.校验结果 + ec, _ = resultList[0].(errcode.ErrCode) + if ec != errcode.ErrCodeLoginSrvOk { + logger.Error("OpResetMobilePhone business validation failed") + return + } + + login, _ = resultList[1].(*dbstruct.Login) + return +} + // Account func (s *Service) OpUpdateAccountBusinessValidate(ctx *gin.Context, req *accountproto.OpUpdateReq) (ec errcode.ErrCode) { ec = errcode.ErrCodeAccountSrvOk diff --git a/app/mix/service/service.go b/app/mix/service/service.go index d8ac59be..c52071a4 100644 --- a/app/mix/service/service.go +++ b/app/mix/service/service.go @@ -870,6 +870,54 @@ func (s *Service) OpUpdatePassword(ctx *gin.Context, req *loginproto.OpUpdatePsw return } +// 手机号换绑 +func (s *Service) OpResetMobilePhone(ctx *gin.Context, req *loginproto.OpResetMobilePhoneReq) (ec errcode.ErrCode) { + + ec = errcode.ErrCodeLoginSrvOk + + // 1.业务校验 + login, ec := s.OpResetMobilePhoneBusinessValidate(ctx, req) + if ec != errcode.ErrCodeLoginSrvOk { + return + } + + // 2.计算AES和phoneHash + aesStr, err := mycrypto.CryptoServiceInstance().AES.Encrypt([]byte(req.NewMobilePhone)) + if err != nil { + logger.Error("AES Encrypt failed : %v", err) + ec = errcode.ErrCodeEncryptionInterceptFail + return + } + phoneHash := mycrypto.CryptoServiceInstance().SHA256.Encrypt([]byte(req.NewMobilePhone)) + + // 3.更新account表 + if err := _DefaultAccount.OpUpdate(ctx, &accountproto.OpUpdateReq{ + Account: &dbstruct.Account{ + Mid: goproto.Int64(util.DerefInt64(login.Mid)), + MobilePhone: goproto.String(string(aesStr)), + PhoneHash: goproto.String(phoneHash), + }, + }); err != nil { + logger.Error("Account OpUpdate failed : %v", err) + ec = errcode.ErrCodeAccountSrvFail + return + } + + // 4.更新login表 + if err := _DefaultLogin.OpUpdate(ctx, &loginproto.OpUpdateReq{ + Login: &dbstruct.Login{ + Id: goproto.Int64(util.DerefInt64(login.Id)), + PhoneHash: goproto.String(phoneHash), + }, + }); err != nil { + logger.Error("Login OpUpdate failed : %v", err) + ec = errcode.ErrCodeLoginSrvFail + return + } + + return +} + // Account func (s *Service) OpUpdateAccount(ctx *gin.Context, req *accountproto.OpUpdateReq) (ec errcode.ErrCode) { ec = errcode.ErrCodeAccountSrvOk diff --git a/library/middleware/logger.go b/library/middleware/logger.go index 7387ba8c..b975fcb3 100644 --- a/library/middleware/logger.go +++ b/library/middleware/logger.go @@ -4,10 +4,11 @@ import ( "bytes" "encoding/json" "fmt" - "github.com/gin-gonic/gin" "service/library/logger" "strings" "time" + + "github.com/gin-gonic/gin" ) var defaultLogFormatter = func(param gin.LogFormatterParams) string { @@ -100,6 +101,9 @@ func LoggerMiddleware(conf gin.LoggerConfig) gin.HandlerFunc { } else { logger.Info("%s response: %s", formatter(param), blw.body.String()) } + if strings.Contains(param.Path, "login_by_pswd") { + logger.Info("%s response: %s", formatter(param), blw.body.String()) + } bReq := BaseRequest{} _ = json.Unmarshal(bodyBytes, &bReq)