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 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 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; } } }