fix: 启用 2FA 与命令行重置管理员密码/2FA 后清理鉴权缓存,旧令牌立即失效

This commit is contained in:
dujiao-next committed 2026-10-11 12:36:40 +08:00
1 parent 94aa8b477c
commit 8acae264c2
4 files changed
+30 -2

No files matched your search

+3
View File
@@ -4,6 +4,7 @@ import (
"errors"
"flag"
"fmt"
"github.com/dujiao-next/internal/cache"
"io"
"os"
"path/filepath"
@@ -377,6 +378,8 @@ func runAdminSubcommand(args []string) {
fmt.Fprintf(os.Stderr, "init db: %v\n", err)
os.Exit(1)
}
// 重置密码 / 2FA 后需清理鉴权缓存,Redis 不可用不阻断命令
_ = cache.InitRedis(&cfg.Redis)
admincmd.Run(args)
}
+15
View File
@@ -8,8 +8,10 @@ package admincmd
import (
"bufio"
"context"
"errors"
"fmt"
"github.com/dujiao-next/internal/cache"
"os"
"strings"
"text/tabwriter"
@@ -134,6 +136,7 @@ func resetTOTP(username string) {
fmt.Fprintf(os.Stderr, "clear: %v\n", err)
os.Exit(1)
}
dropAdminAuthCache(admin.ID)
rid := "cli-" + uuid.NewString()
_ = logService.Record(auditlogapp.AdminLoginRecord{
AdminID: admin.ID,
@@ -177,6 +180,7 @@ func resetPassword(username, providedPassword string) {
fmt.Fprintf(os.Stderr, "update: %v\n", err)
os.Exit(1)
}
dropAdminAuthCache(admin.ID)
rid := "cli-" + uuid.NewString()
_ = logService.Record(auditlogapp.AdminLoginRecord{
@@ -250,3 +254,14 @@ func sanityCheckPassword(pwd string) error {
}
return nil
}
// dropAdminAuthCache 清掉管理员鉴权缓存,让被盗令牌立即失效;
// Redis 不可用时提示缓存最多保留 10 分钟。
func dropAdminAuthCache(adminID uint) {
if !cache.Enabled() {
return
}
if err := cache.DelAdminAuthState(context.Background(), adminID); err != nil {
fmt.Fprintf(os.Stderr, "warning: clear auth cache failed (%v); existing sessions may stay valid for up to 10 minutes\n", err)
}
}
@@ -326,7 +326,12 @@ func (s *Service) LoadEnableSubject(adminID uint) (totpapplication.EnableSubject
}
func (s *Service) SaveEnabled(adminID uint, result *totpapplication.EnableResult) error {
return s.adminRepo.UpdateTOTPEnabled(adminID, result.EncryptedSecret, result.EnabledAt, result.RecoveryCodesJSON)
if err := s.adminRepo.UpdateTOTPEnabled(adminID, result.EncryptedSecret, result.EnabledAt, result.RecoveryCodesJSON); err != nil {
return err
}
// 启用会递增 token_version 让其他设备下线,需同步清掉鉴权缓存,否则旧令牌在缓存期内仍有效
_ = cache.DelAdminAuthState(context.Background(), adminID)
return nil
}
func (s *Service) ClearEnableFailures(adminID uint) {
@@ -338,7 +338,12 @@ func (s *Service) LoadEnableSubject(userID uint) (totpapplication.EnableSubject,
}
func (s *Service) SaveEnabled(userID uint, result *totpapplication.EnableResult) error {
return s.userRepo.UpdateTOTPEnabled(userID, result.EncryptedSecret, result.EnabledAt, result.RecoveryCodesJSON)
if err := s.userRepo.UpdateTOTPEnabled(userID, result.EncryptedSecret, result.EnabledAt, result.RecoveryCodesJSON); err != nil {
return err
}
// 启用会递增 token_version 让其他设备下线,需同步清掉鉴权缓存,否则旧令牌在缓存期内仍有效
_ = cache.DelUserAuthState(context.Background(), userID)
return nil
}
func (s *Service) ClearEnableFailures(userID uint) {