From bd6b518aae61608ddc2d82b43ccc283dc95b9c54 Mon Sep 17 00:00:00 2001
From: Junjie <fallin.jie@qq.com>
Date: 星期三, 11 三月 2026 13:59:33 +0800
Subject: [PATCH] #

---
 src/main/java/com/zy/common/auth/MfaLoginTicketManager.java |   73 ++++++++++++++++++++++++++++++++++++
 1 files changed, 73 insertions(+), 0 deletions(-)

diff --git a/src/main/java/com/zy/common/auth/MfaLoginTicketManager.java b/src/main/java/com/zy/common/auth/MfaLoginTicketManager.java
new file mode 100644
index 0000000..85ae878
--- /dev/null
+++ b/src/main/java/com/zy/common/auth/MfaLoginTicketManager.java
@@ -0,0 +1,73 @@
+package com.zy.common.auth;
+
+import com.core.common.Cools;
+import org.springframework.stereotype.Component;
+
+import java.security.SecureRandom;
+import java.util.Base64;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Component
+public class MfaLoginTicketManager {
+
+    private static final long EXPIRE_MILLIS = 5 * 60 * 1000L;
+
+    private final SecureRandom secureRandom = new SecureRandom();
+    private final ConcurrentHashMap<String, TicketHolder> holders = new ConcurrentHashMap<>();
+
+    public String create(Long userId) {
+        cleanup();
+        String ticket;
+        do {
+            ticket = randomTicket();
+        } while (holders.putIfAbsent(ticket, new TicketHolder(userId, System.currentTimeMillis() + EXPIRE_MILLIS)) != null);
+        return ticket;
+    }
+
+    public Long getUserId(String ticket) {
+        if (Cools.isEmpty(ticket)) {
+            return null;
+        }
+        TicketHolder holder = holders.get(ticket);
+        if (holder == null) {
+            return null;
+        }
+        if (holder.expireAt < System.currentTimeMillis()) {
+            holders.remove(ticket);
+            return null;
+        }
+        return holder.userId;
+    }
+
+    public void remove(String ticket) {
+        if (!Cools.isEmpty(ticket)) {
+            holders.remove(ticket);
+        }
+    }
+
+    private void cleanup() {
+        long now = System.currentTimeMillis();
+        for (Map.Entry<String, TicketHolder> entry : holders.entrySet()) {
+            if (entry.getValue().expireAt < now) {
+                holders.remove(entry.getKey());
+            }
+        }
+    }
+
+    private String randomTicket() {
+        byte[] bytes = new byte[24];
+        secureRandom.nextBytes(bytes);
+        return Base64.getUrlEncoder().withoutPadding().encodeToString(bytes);
+    }
+
+    private static final class TicketHolder {
+        private final Long userId;
+        private final long expireAt;
+
+        private TicketHolder(Long userId, long expireAt) {
+            this.userId = userId;
+            this.expireAt = expireAt;
+        }
+    }
+}

--
Gitblit v1.9.1