feat: 密码错误时禁用token并每3秒输出一次提示
This commit is contained in:
parent
8ae1ded87f
commit
f7efcc5378
@ -80,6 +80,17 @@ func (r *GoodsRepository) MarkFailed(id int64) {
|
||||
}
|
||||
}
|
||||
|
||||
// DisableToken 禁用Token(设置is_enable=0)
|
||||
func (r *GoodsRepository) DisableToken(id int64) {
|
||||
query := `UPDATE kfz_token SET is_enable = 0 WHERE id = ?`
|
||||
_, err := database.DB.Exec(query, id)
|
||||
if err != nil {
|
||||
log.Printf("[Repo/Goods] 禁用Token失败: id=%d, 错误=%v", id, err)
|
||||
} else {
|
||||
log.Printf("[Repo/Goods] 禁用Token成功: id=%d", id)
|
||||
}
|
||||
}
|
||||
|
||||
// GetByID 根据ID查询记录
|
||||
func (r *GoodsRepository) GetByID(id int64) (*GoodsPricing, error) {
|
||||
query := `SELECT id, isbn, out_id, quality, query_index, user_id, price, shipping_fee FROM goods_pricing WHERE id = ?`
|
||||
|
||||
@ -27,6 +27,11 @@ type GoodsService struct {
|
||||
tokenRepository *repository.TokenRepository
|
||||
currentTokenIndex int
|
||||
tokenMu sync.Mutex
|
||||
|
||||
badPasswords map[string]bool
|
||||
badPWMu sync.Mutex
|
||||
alertStartedMu sync.Mutex
|
||||
alertStarted bool
|
||||
}
|
||||
|
||||
// NewGoodsService 创建商品服务实例
|
||||
@ -38,6 +43,7 @@ func NewGoodsService(proxy string, apiRateLimitSeconds int, callbackURL string,
|
||||
callbackURL: callbackURL,
|
||||
tokenRepository: tokenRepo,
|
||||
currentTokenIndex: 0,
|
||||
badPasswords: make(map[string]bool),
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,6 +143,51 @@ func (s *GoodsService) sendCallback(outID, userID string, price, shippingFee flo
|
||||
}
|
||||
}
|
||||
|
||||
// reportBadPassword 记录密码错误并启动每3秒输出一次提示
|
||||
func (s *GoodsService) reportBadPassword(username string) {
|
||||
s.badPWMu.Lock()
|
||||
if s.badPasswords[username] {
|
||||
s.badPWMu.Unlock()
|
||||
return
|
||||
}
|
||||
s.badPasswords[username] = true
|
||||
s.badPWMu.Unlock()
|
||||
|
||||
log.Printf("[BadPassword] 孔网账号密码错误: username=%s, 已禁用该token, 每3秒输出一次提示", username)
|
||||
|
||||
s.alertStartedMu.Lock()
|
||||
if s.alertStarted {
|
||||
s.alertStartedMu.Unlock()
|
||||
return
|
||||
}
|
||||
s.alertStarted = true
|
||||
s.alertStartedMu.Unlock()
|
||||
|
||||
go func() {
|
||||
ticker := time.NewTicker(3 * time.Second)
|
||||
defer ticker.Stop()
|
||||
for range ticker.C {
|
||||
s.badPWMu.Lock()
|
||||
if len(s.badPasswords) == 0 {
|
||||
s.badPWMu.Unlock()
|
||||
s.alertStartedMu.Lock()
|
||||
s.alertStarted = false
|
||||
s.alertStartedMu.Unlock()
|
||||
return
|
||||
}
|
||||
users := make([]string, 0, len(s.badPasswords))
|
||||
for u := range s.badPasswords {
|
||||
users = append(users, u)
|
||||
}
|
||||
s.badPWMu.Unlock()
|
||||
|
||||
for _, u := range users {
|
||||
log.Printf("[BadPassword] 孔网账号或密码错误: username=%s, 请更新密码后重新登录", u)
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// StartTimerScheduler 启动定时器
|
||||
func (s *GoodsService) StartTimerScheduler(intervalSeconds int) {
|
||||
log.Printf("[TimerScheduler] 定时器启动, 间隔=%d秒", intervalSeconds)
|
||||
@ -298,6 +349,11 @@ func (s *GoodsService) doKfzSearch(kfzUrl, token string, tokenRecord *repository
|
||||
log.Printf("[outGetAllGoods] Token已失效, 尝试自动重新登录: username=%s, id=%d", tokenRecord.Username, tokenRecord.ID)
|
||||
newToken, refreshErr := s.TryRefreshToken(tokenRecord.ID, tokenRecord.Username, tokenRecord.Password)
|
||||
if refreshErr != nil {
|
||||
if refreshErr == ErrPasswordWrong {
|
||||
s.goodsRepository.DisableToken(tokenRecord.ID)
|
||||
s.reportBadPassword(tokenRecord.Username)
|
||||
return nil, refreshErr
|
||||
}
|
||||
log.Printf("[outGetAllGoods] 自动重新登录失败: %v", refreshErr)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ package service
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
@ -11,6 +12,9 @@ import (
|
||||
"github.com/parnurzeal/gorequest"
|
||||
)
|
||||
|
||||
// ErrPasswordWrong 账号或密码错误,不再重试
|
||||
var ErrPasswordWrong = errors.New("孔网账号或密码错误")
|
||||
|
||||
// UserInfo 孔网用户信息结构体
|
||||
type UserInfo struct {
|
||||
UserID int64 `json:"userId"` // 用户ID
|
||||
@ -127,11 +131,15 @@ func OutKfzGetUserInfo(token string) (*UserInfo, error) {
|
||||
}
|
||||
|
||||
// TryRefreshToken 尝试用保存的密码重新登录,更新token。成功返回新token
|
||||
// 密码错误时返回 ErrPasswordWrong
|
||||
func (s *GoodsService) TryRefreshToken(tokenID int64, username, password string) (string, error) {
|
||||
log.Printf("[RefreshToken] 开始重新登录: username=%s, tokenID=%d", username, tokenID)
|
||||
newToken, err := OutKfzLogin(username, password)
|
||||
if err != nil {
|
||||
log.Printf("[RefreshToken] 重新登录失败: username=%s, 错误=%v", username, err)
|
||||
if strings.Contains(err.Error(), "账号或密码错误") {
|
||||
return "", ErrPasswordWrong
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
// 更新数据库中的token
|
||||
|
||||
Loading…
Reference in New Issue
Block a user