From da88a501ad6b17dfd5773a1212c440653532b379 Mon Sep 17 00:00:00 2001 From: RockYang Date: Tue, 4 Jul 2023 17:15:02 +0800 Subject: [PATCH] =?UTF-8?q?opt:=20=E4=BC=98=E5=8C=96=E9=AA=8C=E8=AF=81?= =?UTF-8?q?=E7=A0=81=E5=8F=91=E9=80=81=E9=80=BB=E8=BE=91=EF=BC=8C=E5=8A=A0?= =?UTF-8?q?=E5=85=A5=E9=98=B2=E5=88=B7=E9=AA=8C=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/go/handler/user_handler.go | 11 ++++--- api/go/handler/verify_handler.go | 54 ++++++++++++++++++++++++++------ api/go/store/leveldb.go | 13 ++------ api/go/test/test.go | 3 +- web/src/components/SendMsg.vue | 2 +- 5 files changed, 56 insertions(+), 27 deletions(-) diff --git a/api/go/handler/user_handler.go b/api/go/handler/user_handler.go index 0a7be51a..4f3603fe 100644 --- a/api/go/handler/user_handler.go +++ b/api/go/handler/user_handler.go @@ -58,8 +58,10 @@ func (h *UserHandler) Register(c *gin.Context) { // 检查验证码 key := CodeStorePrefix + data.Mobile - code, err := h.levelDB.Get(key) - if err != nil || int(code.(float64)) != data.Code { + var code int + err := h.levelDB.Get(key, &code) + if err != nil || code != data.Code { + logger.Info(code) resp.ERROR(c, "短信验证码错误") return } @@ -356,8 +358,9 @@ func (h *UserHandler) BindMobile(c *gin.Context) { // 检查验证码 key := CodeStorePrefix + data.Mobile - code, err := h.levelDB.Get(key) - if err != nil || int(code.(float64)) != data.Code { + var code int + err := h.levelDB.Get(key, &code) + if err != nil || code != data.Code { resp.ERROR(c, "短信验证码错误") return } diff --git a/api/go/handler/verify_handler.go b/api/go/handler/verify_handler.go index a28c36cd..7de5a31b 100644 --- a/api/go/handler/verify_handler.go +++ b/api/go/handler/verify_handler.go @@ -7,6 +7,7 @@ import ( "chatplus/store" "chatplus/utils" "chatplus/utils/resp" + "fmt" "time" "github.com/gin-gonic/gin" @@ -20,8 +21,9 @@ type VerifyHandler struct { db *store.LevelDB } -const TokenStorePrefix = "/tokens/" -const CodeStorePrefix = "/codes/" +const TokenStorePrefix = "/verify/tokens/" +const CodeStorePrefix = "/verify/codes/" +const MobileStatPrefix = "/verify/stats/" func NewVerifyHandler(app *core.AppServer, sms *service.AliYunSmsService, db *store.LevelDB) *VerifyHandler { handler := &VerifyHandler{sms: sms, db: db} @@ -34,11 +36,24 @@ type VerifyToken struct { Timestamp int64 } +// CodeStats 验证码发送统计 +type CodeStats struct { + Mobile string + Count uint + Time int64 +} + // Token 生成自验证 token func (h *VerifyHandler) Token(c *gin.Context) { - // 确保是通过浏览器访问 + // 如果不是通过浏览器访问,则返回错误的 token if c.GetHeader("Sec-Fetch-Mode") != "cors" { - resp.HACKER(c) + token := fmt.Sprintf("%s:%d", utils.RandString(32), time.Now().Unix()) + encrypt, err := utils.AesEncrypt(h.App.Config.AesEncryptKey, []byte(token)) + if err != nil { + resp.ERROR(c, "Token 加密出错") + return + } + resp.SUCCESS(c, encrypt) return } @@ -85,17 +100,31 @@ func (h *VerifyHandler) SendMsg(c *gin.Context) { return } - _, err = h.db.Get(TokenStorePrefix + token.Token) - if err != nil { - resp.HACKER(c) - return - } - if time.Now().Unix()-token.Timestamp > 30 { resp.ERROR(c, "Token 已过期,请刷新页面重试") return } + // 验证当前手机号发送次数,24 小时内相同手机号只允许发送 2 次 + var stat CodeStats + err = h.db.Get(MobileStatPrefix+data.Mobile, &stat) + if err != nil { + logger.Error(err) + stat = CodeStats{ + Mobile: data.Mobile, + Count: 0, + Time: time.Now().Unix(), + } + } else if stat.Count == 2 { + if time.Now().Unix()-stat.Time > 86400 { + stat.Count = 0 + stat.Time = time.Now().Unix() + } else { + resp.ERROR(c, "触发流量预警,请 24 小时后再操作!") + return + } + } + code := utils.RandomNumber(6) err = h.sms.SendVerifyCode(data.Mobile, code) if err != nil { @@ -112,5 +141,10 @@ func (h *VerifyHandler) SendMsg(c *gin.Context) { return } + // 更新发送次数 + stat.Count = stat.Count + 1 + _ = h.db.Put(MobileStatPrefix+data.Mobile, stat) + logger.Infof("%+v", stat) + resp.SUCCESS(c) } diff --git a/api/go/store/leveldb.go b/api/go/store/leveldb.go index 18bf9d5a..8a1a3ca8 100644 --- a/api/go/store/leveldb.go +++ b/api/go/store/leveldb.go @@ -3,7 +3,6 @@ package store import ( "chatplus/store/vo" "encoding/json" - "github.com/syndtr/goleveldb/leveldb" "github.com/syndtr/goleveldb/leveldb/util" ) @@ -30,19 +29,13 @@ func (db *LevelDB) Put(key string, value interface{}) error { return db.driver.Put([]byte(key), bytes, nil) } -func (db *LevelDB) Get(key string) (interface{}, error) { +func (db *LevelDB) Get(key string, value interface{}) error { bytes, err := db.driver.Get([]byte(key), nil) if err != nil { - return nil, err + return err } - var value interface{} - err = json.Unmarshal(bytes, &value) - if err != nil { - return nil, err - } - - return value, nil + return json.Unmarshal(bytes, &value) } func (db *LevelDB) Search(prefix string) []string { diff --git a/api/go/test/test.go b/api/go/test/test.go index dd096565..cfe7bfdf 100644 --- a/api/go/test/test.go +++ b/api/go/test/test.go @@ -17,8 +17,7 @@ import ( ) func main() { - //testAesEncrypt() - fmt.Println(utils.RandomNumber(6)) + testAesEncrypt() } // Http client 取消操作 diff --git a/web/src/components/SendMsg.vue b/web/src/components/SendMsg.vue index 7abb5b8b..bc0af64d 100644 --- a/web/src/components/SendMsg.vue +++ b/web/src/components/SendMsg.vue @@ -31,7 +31,7 @@ const sendMsg = () => { httpGet('/api/verify/token').then(res => { httpPost('/api/verify/sms', {token: res.data, mobile: props.mobile}).then(() => { ElMessage.success('短信发送成功') - let time = 120 + let time = 10 btnText.value = time const handler = setInterval(() => { time = time - 1