SFT/mock-server/state.js

47 lines
1.8 KiB
JavaScript

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