fix: 迁移清理改为精确匹配同设备,避免误删其他设备会话

- 用 UA+IP 精确匹配同设备旧会话,而非 DeleteByUID 清除所有会话
- 降级期重新登录的设备:清理旧记录避免重复
- 降级期未操作的设备:保留会话,恢复后无需重新登录
This commit is contained in:
2026-05-31 12:29:31 +08:00
parent 2da24e12ff
commit 891990bb35

View File

@ -112,19 +112,22 @@ func (fs *FallbackStore) migrateSessions() {
return
}
// 收集迁移涉及的用户
userSet := make(map[uint]bool, len(sessions))
for _, s := range sessions {
userSet[s.UserID] = true
}
ctx := context.Background()
// 清理 Redis 中同用户的旧会话(降级期间用户重新登录,旧会话已失效
// 避免 Redis 恢复后出现新旧两条会话并存、设备列表重复
for uid := range userSet {
if err := fs.redis.DeleteByUID(uid); err != nil {
log.Printf("[FallbackStore] 迁移前清理旧会话失败 uid=%d err=%v", uid, err)
// 清理 Redis 中同设备的旧会话(仅针对降级期间重新登录的设备
// 匹配规则:同一用户 + 同 UserAgent + 同 IP 的旧会话视为同设备残留,其他设备会话保留
for _, migrated := range sessions {
oldSessions, err := fs.redis.ListByUID(migrated.UserID)
if err != nil {
log.Printf("[FallbackStore] 迁移时查找旧会话失败 uid=%d err=%v", migrated.UserID, err)
continue
}
for _, old := range oldSessions {
if old.IP == migrated.IP && old.UserAgent == migrated.UserAgent {
if delErr := fs.redis.Delete(old.ID); delErr != nil {
log.Printf("[FallbackStore] 迁移时清理同设备旧会话失败 sid=%s err=%v", old.ID[:16]+"...", delErr)
}
}
}
}
@ -155,7 +158,7 @@ func (fs *FallbackStore) migrateSessions() {
_ = fs.memory.Delete(s.ID)
}
log.Printf("[FallbackStore] Redis 已恢复,静默迁移 %d 条会话(旧会话已清理,内存已释放)", len(sessions))
log.Printf("[FallbackStore] Redis 已恢复,静默迁移 %d 条会话(内存已释放)", len(sessions))
}
// ping 检查 Redis 连接状态(带超时)