import crypto from 'crypto' // ---------------- 令牌存储 ---------------- export const accessTokens = new Map() // token -> { userId, expireAt } export const refreshTokens = new Map() // token -> { userId, expireAt } export const ACCESS_TOKEN_TTL_MS = 30 * 60 * 1000 export const REFRESH_TOKEN_TTL_MS = 7 * 24 * 60 * 60 * 1000 export function genToken() { return crypto.randomBytes(24).toString('hex') } export function issueTokenPair(userId) { const accessToken = genToken() const refreshToken = genToken() accessTokens.set(accessToken, { userId, expireAt: Date.now() + ACCESS_TOKEN_TTL_MS }) refreshTokens.set(refreshToken, { userId, expireAt: Date.now() + REFRESH_TOKEN_TTL_MS }) return { accessToken, refreshToken } } // ---------------- 短信验证码 ---------------- // key: `${businessType}:${phone}`,value: { code, expireAt } export const smsCodes = new Map() export const SMS_CODE_TTL_MS = 5 * 60 * 1000 export const FIXED_SMS_CODE = '123456' // 万能码,与真实生成码同时有效,便于手动测试 export function genSmsCode(businessType, phone) { const code = String(Math.floor(100000 + Math.random() * 900000)) smsCodes.set(`${businessType}:${phone}`, { code, expireAt: Date.now() + SMS_CODE_TTL_MS }) // eslint-disable-next-line no-console console.log(`[mock-server] 短信验证码 businessType=${businessType} phone=${phone} code=${code}`) return code } export function verifySmsCode(businessType, phone, inputCode) { if (inputCode === FIXED_SMS_CODE) return true const record = smsCodes.get(`${businessType}:${phone}`) if (!record) return false if (record.expireAt < Date.now()) return false return record.code === inputCode } // ---------------- 登录失败次数(连续失败5次锁定) ---------------- export const loginFailCounts = new Map() // username -> count export const MAX_LOGIN_FAIL = 5